linux上TCP connection timeout的原因查找
来源:互联网 发布:前台ajax获取json数据 编辑:程序博客网 时间:2024/06/05 19:30
最近在产线上经常出现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 ?
也就是client 发出 syn 包,server端在你指定的时间内没有回复ack,poll/select 返回0
server 端为什么没有回复ack, 因为syn包的回复是内核层的,要么网络层丢包,要么就是内核层back_log的queue满了,关于backlog在本片中就不详细描述了。
当时查看产线上的连接最高能到1000多,同时查看了backlog 的queue的大小
- cat /proc/sys/net/ipv4/tcp_max_syn_backlog
有8192 在产线上没有这么多的客户端的连接,不可能backlog queue会满
虽然syn_backlog 的设置是8192 但并不代表服务器启动的时候设置成了8192,所以必须查这个端口所设置的backlog大小
- ss -lt
看到Send-Q在8080端口是128 ,原来在服务器端启动listen 的时候设置了128的backlog
查看tomcat 的配置,默认bio的设置
- <Connectorexecutor="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"
- />
产线上已经设置了acceptCount, 默认是100 但是这里设置了是5000 ,这与通过ss看到的send-q的结果严重不符合
通过内核代码分析,发现原来内核参数不仅仅是通过tcp_max_syn_backlog控制,同时也受somaxconn控制
查看
- cat /proc/sys/net/core/somaxconn
- net.core.somaxconn = 8192
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.
- <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;
- }
也就是说当并发超过628个连接以上,就有可能出现backlog queue满的情况,而出现connect timeout的情况,一切皆清楚了。
- linux上TCP connection timeout的原因查找
- linux上TCP connection timeout的原因查找
- IDbConnection的connection timeout 和 IDbcommand.commandTimeout
- Connection Timeout和Command Timeout
- 关于linux下wget出现connection timed out的原因
- NSMutableURLRequest timeout interval 不起作用的原因
- Tomcat内存溢出的原因--Exception in thread “RMI TCP Connection(idle)” ---OutOfMemoryError: PermGen space
- Oracle Terminated Connection Timeout
- restemplate设置connection timeout
- ssh出现connection timeout
- vagrant connection timeout. Retrying...
- Ldap connection timeout error:
- MongoDB connection timeout
- 不支持关键字: “connection timeout”
- 在mysql中connection设置和wait-timeout的设置
- Jedis使用中遇到的一些问题timeout no connection
- Genymotion添加devices时出现Connection timeout occurred的解决办法
- 解决vagrant default: Warning: Connection timeout. Retrying...的问题
- Android 原生导航 IV-实现Drawer+ToolBar+Tab
- 模块分类构件
- 2.5 SGA-缓冲区缓存
- 2.6 查询转换
- 8张图理解Java
- linux上TCP connection timeout的原因查找
- 2.7 视图合并
- PL/SQL编程学习之开篇
- hdu4324 Triangle LOVE(拓扑排序)
- 2.8 子查询解嵌套
- java.lang.IllegalArgumentException: Page directive: invalid value for import 问题处理
- HDOJ 1133 Buy the tickets!
- Linux目录结构及文件操作
- 把Python默认编码更换为utf-8