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 ...
随机推荐
- ThinkPHP分页用异步来做,玩转分页类!
具体为什么用异步来做分页我就不多说了! 用异步来做分页,主要还是看分页类怎么玩! 方便管理,还是把Ajax分页作为一个工具来使用: 同样新建工具类: 多次尝试,最终修改好的分页类是这样的:(我自己使用 ...
- 利用trace重建控制文件
以下步骤,内容都在ora11g_ora_.trc文件中 CREATE CONTROLFILE REUSE DATABASE "ORA11G" NORESETLOGS ARCHIV ...
- linux .zip 解压命令集
zip: 压缩: zip [-AcdDfFghjJKlLmoqrSTuvVwXyz$][-b <工作目录>][-ll][-n <字尾字符串>][-t <日期时间>] ...
- Java 笔记20180123
在批量添加数据时候采用List或者Map或者SetSet<Student> students = new Set<Student>();// 客户端验证:js:服务器端验证:必 ...
- No module named pip.req
https://stackoverflow.com/questions/25192794/no-module-named-pip-req#
- 爬虫之BeautifulSoup
BeautifulSoup是一个模块,该模块用于接收一个HTML或XML字符串,然后将其进行格式化,之后便可以使用他提供的方法进行快速查找指定元素,从而使得在HTML或XML中查找指定元素变得简单. ...
- (4.20)sql server性能指标、性能计数器
(4.20)sql server性能指标.性能计数器 常规计数器 收集操作系统服务器的服务器性能信息,包括Processor.磁盘.网络.内存 Processor 处理器 1.1 % Processo ...
- Spark Core (一) 什么是RDD的Transformation和Action以及Dependency(转载)
1. Spark的RDD RDD(Resilient Distributed Datasets),弹性分布式数据集,是对分布式数据集的一种抽象. RDD所具备5个主要特性: 一组分区列表 计算每一个数 ...
- 20165324_mypwd
20165324_mypwd 实验要求 实验要求 学习pwd命令 研究pwd实现需要的系统调用(man -k; grep),写出伪代码 实现mypwd 测试mypwd 背景知识 文件存储结构 介绍文件 ...
- jsoup做http接口测试
本文转载张飞的博客http://www.cnblogs.com/zhangfei/p/4359408.html在此感谢博主的分享! 最早用Jsoup是有一个小的爬虫应用要写,发现Jsoup较HttpC ...