linux上TCP connection timeout问题解决办法
最近在产线上经常出现connection timeout的问题,先看看Java 中关于connection timeout 的异常如何产生
JAVA中的timeout
java.net.SocketTimeoutException: connect timed out 客户端异常:connect timed out at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589)
我们能经常看到的connect timed out异常产生,看一下java 是如何生成这个异常
plainsocketimpl.c 中
while (1) { jlong newTime; #ifndef USE_SELECT { struct pollfd pfd; pfd.fd = fd; pfd.events = POLLOUT; errno = 0; connect_rv = NET_Poll(&pfd, 1, timeout); } #else { fd_set wr, ex; struct timeval t; t.tv_sec = timeout / 1000; t.tv_usec = (timeout % 1000) * 1000; FD_ZERO(&wr); FD_SET(fd, &wr); FD_ZERO(&ex); FD_SET(fd, &ex); errno = 0; connect_rv = NET_Select(fd+1, 0, &wr, &ex, &t); } #endif if (connect_rv >= 0) { break; } if (errno != EINTR) { break; } /* * The poll was interrupted so adjust timeout and * restart */ newTime = JVM_CurrentTimeMillis(env, 0); timeout -= (newTime - prevTime); if (timeout <= 0) { connect_rv = 0; break; } prevTime = newTime; } /* while */ if (connect_rv == 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", "connect timed out"); /* * Timeout out but connection may still be established. * At the high level it should be closed immediately but * just in case we make the socket blocking again and * shutdown input & output. */ SET_BLOCKING(fd); JVM_SocketShutdown(fd, 2); return; }
这里可以看到在做connect的时候,是调用 NET_Poll 或者 NET_Select, 在linux 上就是使用 poll/select
当发生timeout的时候connect_rv=0 ,这里有个注意点虽然在poll/select 是传入timeout的时间,但是这是会被打断的,connect_rv返回的值为-1 ,所以jvm里面重新计算了timeout , 确保timeout 的时间片已经运行完了,才推出循环。
newTime = JVM_CurrentTimeMillis(env, 0); timeout -= (newTime - prevTime); if (timeout <= 0) { connect_rv = 0; break; }
同时设置connect_rv 为0, 也是下面只有当connect_rv为0的时候才抛出connect timeout
什么是connect timeout "htmlcode">
有8192 在产线上没有这么多的客户端的连接,不可能backlog queue会满,虽然syn_backlog 的设置是8192 但并不代表服务器启动的时候设置成了8192,所以必须查这个端口所设置的backlog大小 看到Send-Q在8080端口是128 ,原来在服务器端启动listen 的时候设置了128的backlog 查看tomcat 的配置,默认bio的设置 产线上已经设置了acceptCount, 默认是100 但是这里设置了是5000 ,这与通过ss看到的send-q的结果严重不符合 发现值是128, OK 原因找到了,修改/etc/sysctl.conf 添加 sysctl -f /etc/sysctl.conf 重新加载一下,这样就能改变全局了 问题:是1000多个连接,500个工作线程,因为backlog的大小是受socket.accept控制的,我们通常境况下会单独起一个线程去serversocket.accept(),而当前server的load并不高,不因该会出现back_log queue出现满的情况,更何况只有1000多个连接,代码就是真相,查看tomcat的源码。 原来accptor 线程在accept 之前,会去countUpOrWaitConnection 发现接受到的的socket数目大于设置的work线程数目的时候,会停止accept. 也就是说当并发超过628个连接以上,就有可能出现backlog queue满的情况,而出现connect timeout的情况,一切皆清楚了。 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
cat /proc/sys/net/ipv4/tcp_max_syn_backlog
ss -lt
<Connector executor="tomcatThreadPool"
port="8080"
protocol="HTTP/1.1"
acceptCount="5000"
connectionTimeout="25000"
maxHttpHeaderSize="8192"
useBodyEncodingForURI="true"
enableLookups="false"
redirectPort="8443"
URIEncoding="UTF-8"
maxThreads="500"
maxKeepAliveRequests="1000"
keepAliveTimeout="30000"
/>
通过内核代码分析,发现原来内核参数不仅仅是通过tcp_max_syn_backlog控制,同时也受somaxconn控制
查看
cat /proc/sys/net/core/somaxconn
net.core.somaxconn = 8192
<strong>countUpOrAwaitConnection</strong>();
Socket socket = null;
try {
// Accept the next incoming connection from the server
// socket
socket = serverSocketFactory.acceptSocket(serverSocket);
} catch (IOException ioe) {
countDownConnection();
// Introduce delay if necessary
errorDelay = handleExceptionWithDelay(errorDelay);
// re-throw
throw ioe;
}
更新日志
- 曾轶可.2011-一只猫的旅行【天娱传媒】【WAV+CUE】
- 黑神话悟空上品狼刺客精魄获取方法一览|上品狼刺客精魄收集攻略
- 视觉小说《神椿市建设中REGENERATE》将于2025年2月20日发售
- 黑神话悟空上品鼠弩手精魄获取方法一览|上品鼠弩手精魄收集攻略
- 中国音乐地图听见世界非物质文化遗产《非遗HQCD》wav
- 中国民乐合奏作品集《华夏之音HQ》头版限量编号[WAV+CUE]
- [电影原声带]黎允文《天将雄师》[FLAC+CUE]
- 曝NS继任机型已进入量产阶段:已花了30亿日元
- 不是Switch2?曝《马里奥惊奇》NS捆绑包即将公开
- 暖心任天堂!网友Switch维修返还时贴纸被完好保留
- 《国语老歌 经典对唱情歌 2CD》[WAV/分轨][1.1GB]
- 《刀郎 翻唱精选华语专辑 披着羊皮的狼 》[WAV+CUE][430MB]
- 《真的田震 中国乐坛红极一时的歌者 精品集》[WAV+CUE][300MB]
- 群星.1995-新滚石九大天王之情歌大全【滚石】【WAV+CUE】
- 群星.1993-滚石九大天王十二出好戏·纵夏欢唱【滚石】【WAV+CUE】