Java网络编程学习A轮_04_TCP连接异常
参考资料:
https://huoding.com/2016/01/19/488
示例代码:
https://github.com/gordonklg/study,socket module
A. CLOSE_WAIT
有时会出现服务器响应极慢、假死的现象,查看 netstat 会发现服务器上存在大量未关闭的 CLOSE_WAIT 状态连接。我们分析下原因。
首先,CLOSE_WAIT 是被动关闭方才会出现的状态。我们模拟一个场景,客户端建立大量 Socket 连接,同时为每个 Socket 设置超时时间,并且在发生超时时关闭 Socket;服务器端不发送数据也不关闭 Socket。对应测试代码如下:
gordon.study.socket.basic.wireshark.MockSocketTimeoutThenServerCloseWait_Server.java
public class MockSocketTimeoutThenServerCloseWait_Server {
@SuppressWarnings("resource")
public static void main(String[] args) throws Exception {
Set<Socket> set = new HashSet<>();
ServerSocket serverSocket = new ServerSocket(8888);
while (true) {
Socket socket = serverSocket.accept();
set.add(socket); // anti gc.
}
}
}
gordon.study.socket.basic.wireshark.MockSocketTimeoutThenServerCloseWait_Client.java
public class MockSocketTimeoutThenServerCloseWait_Client {
public static void main(String[] args) throws Exception {
for (int i = 0; i < 100; i++) {
Thread.sleep(30);
new Thread(new SocketClient()).start();
}
}
private static class SocketClient implements Runnable {
@Override
public void run() {
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(8888));
socket.setSoTimeout(1000);
socket.getInputStream().read();
} catch (Exception e) {
System.out.println(e);
}
}
}
}
100个线程创建了100个 Socket 连接,在1秒钟后读超时,留下了100个 CLOSE_WAIT 状态的连接。
CLOSE_WAIT 状态的连接并不占用太多操作系统资源,它只是服务器无响应的一种症状,真正的原因还需要自己分析。
大多数情况下是因为客户端超时直接关闭 Socket,同时服务端没能正确关闭 Socket 导致的。可以通过服务端设置读超时、引入心跳检测等方式修复。
真正的问题是客户端为什么会超时。考虑是否超时时间设置太短、业务流中是否有耗时(但不太耗资源)的操作、是否允许了请求排队但是队伍太长导致等待中就超时了。
B. TIME_WAIT
TIME_WAIT 状态会保持 2 * MSL 时间,这是由 TCP 协议规定的。MSL 是指 TCP 报文段生存的最大时间。
在高并发场景下,例如 TPS 1k,如果 MSL 为60秒,那么可能会有 120k 个 TIME_WAIT 状态的连接。这会占用大量系统资源。
TIME_WAIT 一定是主动关闭方才会有的状态,如下图。我们的模拟场景需要由服务方先关闭 Socket。
gordon.study.socket.basic.wireshark.MockServerTimeWait_Server.java
public class MockServerTimeWait_Server {
@SuppressWarnings("resource")
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(8888);
while (true) {
Socket socket = serverSocket.accept();
socket.close();
}
}
}
gordon.study.socket.basic.wireshark.MockServerTimeWait_Client.java
public class MockServerTimeWait_Client {
public static void main(String[] args) throws Exception {
for (int i = 0; i < 100; i++) {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(8888));
InputStream is = socket.getInputStream();
while (is.read() != -1) {
}
socket.close();
}
}
}
最简单的解决方案就是让客户端作为主动关闭方。被动关闭方是没有 TIME_WAIT 的烦恼的。
Java网络编程学习A轮_04_TCP连接异常的更多相关文章
- Java网络编程学习A轮_01_目标与基础复习
A. A轮目标 复习网络编程基础知识,重点学习下TCP三次握手四次挥手,以及可能引发的异常情况. 回顾 Socket 编程,好多年没写(chao)过相关代码了. 重学 NIO,以前学的基本忘光了,毕竟 ...
- Java网络编程学习A轮_06_NIO入门
参考资料: 老外写的教程,很适合入门:http://tutorials.jenkov.com/java-nio/index.html 上面教程的译文:http://ifeve.com/overview ...
- Java网络编程学习A轮_08_NIO的Reactor模型
参考资料: 了解 Java NIO 的 Reactor 模型,大神 Doug Lea 的 PPT Scalable IO in Java 必看:http://gee.cs.oswego.edu/dl/ ...
- Java网络编程学习A轮_03_抓包分析TCP四次挥手
参考资料: http://www.jellythink.com/archives/705 示例代码: https://github.com/gordonklg/study,socket module ...
- Java网络编程学习A轮_07_基于Buffer的Socket编程
示例代码: https://github.com/gordonklg/study,socket module A. LineSeparate 基于 Buffer 实现逐行读取的 EchoServer ...
- Java网络编程学习A轮_05_Socket编程
示例代码: https://github.com/gordonklg/study,socket module A. Socket 编程简单例子 最简单的 Socket 编程是通过回车/换行符,整行读取 ...
- Java网络编程学习A轮_02_抓包分析TCP三次握手过程
参考资料: https://huoding.com/2013/11/21/299 https://hpbn.co/building-blocks-of-tcp/#three-way-handshake ...
- Java 网络编程学习总结
新手一枚,Java学习中,把自己学习网络编程的知识总结一下,梳理下知识,方便日后查阅,高手莫进. 本文的主要内容: [1] 网络编程认识 [2] TCP/IP编程 ...
- Java网络编程学习笔记
Java网络编程,我们先来看下面这一张图: 由图可得:想要进行网络编程,首先是服务器端通过ServerSocket对某一个端口进行监听.通过accept来判断是否有客户端与其相连.若成功连上,则通过r ...
随机推荐
- Birt报表安装及制作
一.Birt报表安装 二.Birt报表设置 1. file--> new --> Project 如下图所示创建报表工程. 输入工程名称后,创建完成. 2.创建报表 创建报表 完成创建. ...
- poj1821 Fence【队列优化线性DP】
Fence Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 6122 Accepted: 1972 Description ...
- 南京网络赛G-Lpl and Energy【线段树】
During tea-drinking, princess, amongst other things, asked why has such a good-natured and cute Drag ...
- 利用burpsuite实现重放攻击
1.什么是重放攻击? 顾名思义,重复的会话请求就是重放攻击.可能是因为用户重复发起请求,也可能是因为请求被攻击者获取,然后重新发给服务器. 附上详细的解释:http://blog.csdn.net/k ...
- SpringCloud 进阶之Zuul(路由网关)
1. Zuul(路由网关) Zuul 包含了对请求的路由和过滤两个最主要的功能; 路由功能:负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础; 过滤功能:负责对请求的处理过程进行干 ...
- vsftpd文件服务器安装与配置
-d<登入目录>:指定用户登入时的启始目录:. -s<shell>:指定用户登入后所使用的shell: /sbin/nologin指的是不允许login当前Linux系统.当用 ...
- MySQL多个相同结构的表查询并把结果合并放在一起的语句(union all)
union all select *,'1' as category from table1001 where price > 10 union all select *,'2' as cate ...
- (android实战)破解apk
简单的总结几个关键步骤: 一.工具准备:apktool , dex2jar , jd-gui 二.使用dex2jar + jd-gui 得到apk的java源码 1.用解压工具从 apk包中取出 cl ...
- python socket编程 实现简单p2p聊天程序
目标是写一个python的p2p聊天的项目,这里先说一下python socket的基础课程 一.Python Socket 基础课程 Socket就是套接字,作为BSD UNIX的进程通信机制,取后 ...
- 文件名含中文的JavaWeb文件下载
在javaweb项目中实现文件下载,当文件名中包含中文文字时,需要进行如下的处理,才能在浏览器端正常显示中文文件名: response.setContentType("octets/stre ...