一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

Linux|Centos|Ubuntu|系統進程|Fedora|注冊表|Bios|Solaris|Windows7|Windows10|Windows11|windows server|

服務器之家 - 服務器系統 - Linux - linux上TCP connection timeout問題解決辦法

linux上TCP connection timeout問題解決辦法

2022-01-10 16:59raintungli Linux

這篇文章主要介紹了 linux上TCP connection timeout問題解決辦法的相關資料,需要的朋友可以參考下

 linux上TCP connection timeout問題解決辦法

最近在產線上經常出現connection timeout的問題,先看看Java 中關于connection timeout 的異常如何產生

JAVA中的timeout

?
1
2
3
4
5
6
7
8
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)

我們能經??吹降腸onnect timed out異常產生,看一下java 是如何生成這個異常

plainsocketimpl.c 中

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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 的時間片已經運行完了,才推出循環。

?
1
2
3
4
5
6
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的大小

?
1
cat /proc/sys/net/ipv4/tcp_max_syn_backlog

有8192 在產線上沒有這么多的客戶端的連接,不可能backlog queue會滿,雖然syn_backlog 的設置是8192 但并不代表服務器啟動的時候設置成了8192,所以必須查這個端口所設置的backlog大小

?
1
ss -lt

看到Send-Q在8080端口是128 ,原來在服務器端啟動listen 的時候設置了128的backlog

查看tomcat 的配置,默認bio的設置

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<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"
        />

產線上已經設置了acceptCount, 默認是100 但是這里設置了是5000 ,這與通過ss看到的send-q的結果嚴重不符合
通過內核代碼分析,發現原來內核參數不僅僅是通過tcp_max_syn_backlog控制,同時也受somaxconn控制
查看

?
1
cat /proc/sys/net/core/somaxconn

發現值是128, OK 原因找到了,修改/etc/sysctl.conf 添加

?
1
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.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<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的情況,一切皆清楚了。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

原文鏈接:http://blog.csdn.net/raintungli/article/details/37879907

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 精品日韩二区三区精品视频 | 日本热妇 | 欧美不卡一区二区三区免 | 久久中文字幕亚洲精品最新 | 人性本色 | 国产成人91高清精品免费 | 美女张开双腿让男人捅 | 欧美a欧美1级 | 挺进白嫩老师下面视频 | 国产一级持黄大片99久久 | 干妞网免费视频 | 亚洲视频在线一区二区 | 性xxxx中国老妇506070 | 苍井空av| 大陆日韩欧美 | 男人晚上看的 | 人人福利 | 高清男的插曲女的 欢迎你老狼 | 乌克兰肛交影视 | 秋霞理论在一l级毛片 | 欧美a在线观看 | 欧美yw193.c㎝在线观看 | 精品日韩欧美一区二区三区 | 亚洲国产99在线精品一区二区 | 免费国产一级 | 全黄h全肉细节修仙玄幻文 全彩调教侵犯h本子全彩妖气he | 午夜精品久久久久久久99 | 亚洲人成绝费网站色ww | 成品人视频w免费观看w | 狠狠色婷婷日日综合五月 | 国产一区私人高清影院 | 久久久久久久久性潮 | 国产亚洲精品日韩香蕉网 | 国产免费丝袜调教视频 | 深夜免费看 | 亚洲成a人不卡在线观看 | 国产一区私人高清影院 | 国产成人手机在线 | 欧美区在线 | 男生和老师一起差差差 | 美女国内精品自产拍在线播放 |