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 ...
随机推荐
- .Net 获取前端传递的数据
1. DotNet MVC: form是用来获得表单提交的数据:querystring是用来获得标识在URL后面的所有返回的变量及其值. 比如常见的URL网页地址都有xxx.asp?pn=123456 ...
- Jmeter,常见参数 vars、prev、ctx 、props 类的api--beanshell
http://www.cnblogs.com/fnng/p/5827577.html---------jmeter 性能测试 jmeter常见参数 vars.prev.ctx .props 类的api ...
- leetcode之Maximal Square
Given a 2D binary matrix filled with 0's and 1's, find the largest square containing all 1's and ret ...
- 洛谷P4428二进制 [BJOI2018] 线段树
正解:线段树 解题报告: 传送门! 话说开始看到这题的时候我想得hin简单 因为关于%3有个性质就是说一个数的各个位数之和%3=这个数%3嘛,小学基础知识? 我就想着,就直接建一棵树,只是这棵树要用个 ...
- Git学习-->关于Jenkins编译时候,如何获取Git分支的当前分支名?
一.背景 因为代码都迁移到了Gitlab,所以Jenkins编译的时候我们都需要将之前的SVN信息换成现在的Git信息.最近编译一个Lib库的时候,因为团队规定上传Release版本的AAR到Mave ...
- android(十)smali
Dalvik是google专门为Android操作系统设计的一个虚拟机,经过深度的优化.虽然Android上的程序是使用java来开发的,但是Dalvik和标准的java虚拟机JVM还是两回事. Da ...
- java 调用静态方法和构造函数和静态块执行的先后顺序
构造方法是只有你在new对象的时候才会执行,静态语句块和静态方法在类加载到内存的时候就已经执行了,另外,静态语句块只能给静态变量赋值,里面不能出现方法,同样,静态方法里面也不能出现静态语句块 追问: ...
- centos vim编辑器 第八节课
centos vim编辑器 第八节课 其他编辑器: nanogeditemacs 腾讯云上的vim版本~ VIM - Vi IMproved ~ ~ version 7.4.629 ~ by Br ...
- ZOJ2588:Burning Bridges(无向连通图求割边)
题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1588 吐下槽,不得不说ZOJ好坑,模版题做了一个多小时. 题意:* ...
- PAT 1082 Read Number in Chinese[难]
1082 Read Number in Chinese (25 分) Given an integer with no more than 9 digits, you are supposed to ...