成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux中TCP三次握手與四次揮手介紹及調(diào)優(yōu)

系統(tǒng) Linux
TCP是一種面向連接的單播協(xié)議,在發(fā)送數(shù)據(jù)前,通信雙方必須在彼此間建立一條連接。所謂的“連接”,其實(shí)是客戶端和服務(wù)器的內(nèi)存里保存的一份關(guān)于對(duì)方的信息,如ip地址、端口號(hào)等。

[[415215]]

TCP介紹

TCP是一種面向連接的單播協(xié)議,在發(fā)送數(shù)據(jù)前,通信雙方必須在彼此間建立一條連接。所謂的“連接”,其實(shí)是客戶端和服務(wù)器的內(nèi)存里保存的一份關(guān)于對(duì)方的信息,如ip地址、端口號(hào)等。

TCP可以看成是一種字節(jié)流,它會(huì)處理IP層或以下的層的丟包、重復(fù)以及錯(cuò)誤問(wèn)題。在連接的建立過(guò)程中,雙方需要交換一些連接的參數(shù)。這些參數(shù)可以放在TCP頭部。

TCP提供了一種可靠、面向連接、字節(jié)流、傳輸層的服務(wù),采用三次握手建立一個(gè)連接。采用4次揮手來(lái)關(guān)閉一個(gè)連接。

TCP三次握手

客戶端和服務(wù)端通信前要進(jìn)行連接,“3次握手”的作用就是雙方都能明確自己和對(duì)方的收、發(fā)能力是正常的。

  • 第一次握手:客戶端發(fā)送網(wǎng)絡(luò)包,服務(wù)端收到了。這樣服務(wù)端就能得出結(jié)論:客戶端的發(fā)送能力、服務(wù)端的接收能力是正常的。
  • 第二次握手:服務(wù)端發(fā)包,客戶端收到了。這樣客戶端就能得出結(jié)論:服務(wù)端的接收、發(fā)送能力,客戶端的接收、發(fā)送能力是正常的。從客戶端的視角來(lái)看,我接到了服務(wù)端發(fā)送過(guò)來(lái)的響應(yīng)數(shù)據(jù)包,說(shuō)明服務(wù)端接收到了我在第一次握手時(shí)發(fā)送的網(wǎng)絡(luò)包,并且成功發(fā)送了響應(yīng)數(shù)據(jù)包,這就說(shuō)明,服務(wù)端的接收、發(fā)送能力正常。而另一方面,我收到了服務(wù)端的響應(yīng)數(shù)據(jù)包,說(shuō)明我第一次發(fā)送的網(wǎng)絡(luò)包成功到達(dá)服務(wù)端,這樣,我自己的發(fā)送和接收能力也是正常的。
  • 第三次握手:客戶端發(fā)包,服務(wù)端收到了。這樣服務(wù)端就能得出結(jié)論:客戶端的接收、發(fā)送能力,服務(wù)端的發(fā)送、接收能力是正常的。第一、二次握手后,服務(wù)端并不知道客戶端的接收能力以及自己的發(fā)送能力是否正常。而在第三次握手時(shí),服務(wù)端收到了客戶端對(duì)第二次握手作的回應(yīng)。從服務(wù)端的角度,我在第二次握手時(shí)的響應(yīng)數(shù)據(jù)發(fā)送出去了,客戶端接收到了。所以,我的發(fā)送能力是正常的。而客戶端的接收能力也是正常的。

經(jīng)歷了上面的三次握手過(guò)程,客戶端和服務(wù)端都確認(rèn)了自己的接收、發(fā)送能力是正常的。之后就可以正常通信了。

TCP三次握手中的狀態(tài)

在 TCP 三次握手的時(shí)候,Linux 內(nèi)核會(huì)維護(hù)兩個(gè)隊(duì)列,分別是:

  • 半連接隊(duì)列,也稱 SYN 隊(duì)列;
  • 全連接隊(duì)列,也稱 accepet 隊(duì)列;

服務(wù)端收到客戶端發(fā)起的 SYN 請(qǐng)求后,內(nèi)核會(huì)把該連接存儲(chǔ)到半連接隊(duì)列,并向客戶端響應(yīng) SYN+ACK,接著客戶端會(huì)返回 ACK,服務(wù)端收到第三次握手的 ACK 后,內(nèi)核會(huì)把連接從半連接隊(duì)列移除,然后創(chuàng)建新的完全的連接,并將其添加到 accept 隊(duì)列,等待進(jìn)程調(diào)用 accept 函數(shù)時(shí)把連接取出來(lái)。

不管是半連接隊(duì)列還是全連接隊(duì)列,都有最大長(zhǎng)度限制,超過(guò)限制時(shí),內(nèi)核會(huì)直接丟棄,或返回 RST 包。

半連接

很遺憾,我們沒有命令可以查看系統(tǒng)的半連接隊(duì)列數(shù)量。但是我們可以抓住 TCP 半連接的特點(diǎn),就是服務(wù)端處于 SYN_RECV 狀態(tài)的 TCP 連接,就是 TCP 半連接隊(duì)列。使用如下命令計(jì)算當(dāng)前 TCP 半連接隊(duì)列長(zhǎng)度:

  1. $ netstat |grep SYN_RECV |wc -l 
  2. 1723 

SYN_RECV 狀態(tài)下,服務(wù)器必須建立一個(gè) SYN 半連接隊(duì)列來(lái)維護(hù)未完成的握手信息,當(dāng)這個(gè)隊(duì)列溢出后,服務(wù)器將無(wú)法再建立新連接。

如何模擬 TCP 半連接隊(duì)列溢出場(chǎng)景?

模擬 TCP 半連接溢出場(chǎng)景不難,實(shí)際上就是對(duì)服務(wù)端一直發(fā)送 TCP SYN 包,但是不回第三次握手 ACK,這樣就會(huì)使得服務(wù)端有大量的處于 SYN_RECV 狀態(tài)的 TCP 連接。這其實(shí)也就是所謂的 SYN 洪泛、SYN 攻擊、DDos 攻擊。

圖片

實(shí)驗(yàn)環(huán)境:

  • 客戶端和服務(wù)端都是 CentOS Linux release 7.9.2009 (Core) ,Linux 內(nèi)核版本 3.10.0-1160.15.2.el7.x86_64
  • 服務(wù)端 IP 172.16.0.20,客戶端 IP 172.16.0.157
  • 服務(wù)端是 Nginx 服務(wù),端口為 80

本次實(shí)驗(yàn)使用 hping3 工具模擬 SYN 攻擊:

  1. $ hping3 -S -p 80 --flood 172.16.0.20 
  2. HPING 172.16.0.20 (eth0 172.16.0.20): S set, 40 headers + 0 data bytes 
  3. hping in flood mode, no replies will be shown 

新連接建立失敗的原因有很多,怎樣獲得由于隊(duì)列已滿而引發(fā)的失敗次數(shù)呢?netstat -s 命令給出的統(tǒng)計(jì)結(jié)果中可以得到。

  1. $ netstat -s|grep "SYNs to LISTEN" 
  2.     1541918 SYNs to LISTEN sockets dropped 

這里給出的是隊(duì)列溢出導(dǎo)致 SYN 被丟棄的個(gè)數(shù)。注意這是一個(gè)累計(jì)值,如果數(shù)值在持續(xù)增加,則應(yīng)該調(diào)大 SYN 半連接隊(duì)列。修改隊(duì)列大小的方法,是設(shè)置 Linux 的 tcp_max_syn_backlog 參數(shù):

  1. sysctl -w net.ipv4.tcp_max_syn_backlog = 1024 

如果 SYN 半連接隊(duì)列已滿,只能丟棄連接嗎?并不是這樣,開啟 syncookies 功能就可以在不使用 SYN 隊(duì)列的情況下成功建立連接。syncookies 是這么做的:服務(wù)器根據(jù)當(dāng)前狀態(tài)計(jì)算出一個(gè)值,放在己方發(fā)出的 SYN+ACK 報(bào)文中發(fā)出,當(dāng)客戶端返回 ACK 報(bào)文時(shí),取出該值驗(yàn)證,如果合法,就認(rèn)為連接建立成功,如下圖所示。

Linux 下怎樣開啟 syncookies 功能呢?修改 tcp_syncookies 參數(shù)即可,其中值為 0 時(shí)表示關(guān)閉該功能,2 表示無(wú)條件開啟功能,而 1 則表示僅當(dāng) SYN 半連接隊(duì)列放不下時(shí),再啟用它。由于 syncookie 僅用于應(yīng)對(duì) SYN 泛洪攻擊(攻擊者惡意構(gòu)造大量的 SYN 報(bào)文發(fā)送給服務(wù)器,造成 SYN 半連接隊(duì)列溢出,導(dǎo)致正常客戶端的連接無(wú)法建立),這種方式建立的連接,許多 TCP 特性都無(wú)法使用。所以,應(yīng)當(dāng)把 tcp_syncookies 設(shè)置為 1,僅在隊(duì)列滿時(shí)再啟用。

  1. sysctl -w net.ipv4.tcp_syncookies = 1 

全連接

在服務(wù)端可以使用 ss 命令,來(lái)查看 TCP 全連接隊(duì)列的情況:但需要注意的是 ss 命令獲取的 Recv-Q/Send-Q 在「LISTEN 狀態(tài)」和「非 LISTEN 狀態(tài)」所表達(dá)的含義是不同的。從下面的內(nèi)核代碼可以看出區(qū)別:

  1. static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, 
  2.          void *_info) 
  3.  const struct tcp_sock *tp = tcp_sk(sk); 
  4.  struct tcp_info *info = _info; 
  5.  
  6.  if (sk->sk_state == TCP_LISTEN) { 
  7.   r->idiag_rqueue = sk->sk_ack_backlog; 
  8.   r->idiag_wqueue = sk->sk_max_ack_backlog; 
  9.  } else { 
  10.   r->idiag_rqueue = tp->rcv_nxt - tp->copied_seq; 
  11.   r->idiag_wqueue = tp->write_seq - tp->snd_una; 
  12.  } 
  13.  if (info != NULL
  14.   tcp_get_info(sk, info); 

在「LISTEN 狀態(tài)」時(shí),Recv-Q/Send-Q 表示的含義如下:

  1. $ ss -ltnp 
  2. LISTEN     0      1024         *:8081                     *:*                   users:(("java",pid=5686,fd=310)) 
  • Recv-Q:當(dāng)前全連接隊(duì)列的大小,也就是當(dāng)前已完成三次握手并等待服務(wù)端 accept() 的 TCP 連接;
  • Send-Q:當(dāng)前全連接最大隊(duì)列長(zhǎng)度,上面的輸出結(jié)果說(shuō)明監(jiān)聽 8088 端口的 TCP 服務(wù),最大全連接長(zhǎng)度為 1024;

在「非 LISTEN 狀態(tài)」時(shí),Recv-Q/Send-Q 表示的含義如下:

  1. $ ss -tnp 
  2. ESTAB      0      0      172.16.0.20:57672              172.16.0.20:2181                users:(("java",pid=5686,fd=292)) 
  • Recv-Q:已收到但未被應(yīng)用進(jìn)程讀取的字節(jié)數(shù);
  • Send-Q:已發(fā)送但未收到確認(rèn)的字節(jié)數(shù);

如何模擬 TCP 全連接隊(duì)列溢出的場(chǎng)景?

實(shí)驗(yàn)環(huán)境:

  • 客戶端和服務(wù)端都是 CentOS Linux release 7.9.2009 (Core) ,Linux 內(nèi)核版本 3.10.0-1160.15.2.el7.x86_64
  • 服務(wù)端 IP 172.16.0.20,客戶端 IP 172.16.0.157
  • 服務(wù)端是 Nginx 服務(wù),端口為 80

ab是apache bench命令的縮寫。ab是apache自帶的壓力測(cè)試工具。ab非常實(shí)用,它不僅可以對(duì)apache服務(wù)器進(jìn)行網(wǎng)站訪問(wèn)壓力測(cè)試,也可以對(duì)或其它類型的服務(wù)器進(jìn)行壓力測(cè)試。比如nginx、tomcat、IIS等。ab的原理:ab命令會(huì)創(chuàng)建多個(gè)并發(fā)訪問(wèn)線程,模擬多個(gè)訪問(wèn)者同時(shí)對(duì)某一URL地址進(jìn)行訪問(wèn)。它的測(cè)試目標(biāo)是基于URL的,因此,它既可以用來(lái)測(cè)試apache的負(fù)載壓力,也可以測(cè)試nginx、lighthttp、tomcat、IIS等其它Web服務(wù)器的壓力。ab命令對(duì)發(fā)出負(fù)載的計(jì)算機(jī)要求很低,它既不會(huì)占用很高CPU,也不會(huì)占用很多內(nèi)存。但卻會(huì)給目標(biāo)服務(wù)器造成巨大的負(fù)載,其原理類似CC攻擊。自己測(cè)試使用也需要注意,否則一次上太多的負(fù)載。可能造成目標(biāo)服務(wù)器資源耗完,嚴(yán)重時(shí)甚至導(dǎo)致死機(jī)。

TCP 全連接隊(duì)列的最大值取決于 somaxconn 和 backlog 之間的最小值,也就是 min(somaxconn, backlog)。從下面的 Linux 內(nèi)核代碼可以得知:

  1. int __sys_listen(int fd, int backlog) 
  2.  struct socket *sock; 
  3.  int err, fput_needed; 
  4.  int somaxconn; 
  5.  
  6.  sock = sockfd_lookup_light(fd, &err, &fput_needed); 
  7.  if (sock) { 
  8.   somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn; 
  9.   if ((unsigned int)backlog > somaxconn) 
  10.    backlog = somaxconn; 
  11.  
  12.   err = security_socket_listen(sock, backlog); 
  13.   if (!err) 
  14.    err = sock->ops->listen(sock, backlog); 
  15.  
  16.   fput_light(sock->file, fput_needed); 
  17.  } 
  18.  return err; 
  • somaxconn 是 Linux 內(nèi)核的參數(shù),默認(rèn)值是 128,可以通過(guò) /proc/sys/net/core/somaxconn 來(lái)設(shè)置其值;我們?cè)O(shè)置為40000了。
  • backlog 是 listen(int sockfd, int backlog) 函數(shù)中的 backlog 大小,Nginx 默認(rèn)值是 511,可以通過(guò)修改配置文件設(shè)置其長(zhǎng)度;

所以測(cè)試環(huán)境的 TCP 全連接隊(duì)列最大值為 min(128, 511),也就是 511,可以執(zhí)行 ss 命令查看:

  1. ss -tulnp|grep 80 
  2. tcp    LISTEN     0      511       *:80                    *:*                   users:(("nginx",pid=22913,fd=6),("nginx",pid=22912,fd=6),("nginx",pid=22911,fd=6))         
  3. tcp    LISTEN     0      511    [::]:80                 [::]:*                   users:(("nginx",pid=22913,fd=7),("nginx",pid=22912,fd=7),("nginx",pid=22911,fd=7)) 

客戶端執(zhí)行 ab 命令對(duì)服務(wù)端發(fā)起壓力測(cè)試,并發(fā) 1 萬(wàn)個(gè)連接,發(fā)送10萬(wàn)個(gè)包:

  1. -n表示總的請(qǐng)求數(shù)為10000 
  2. -c表示并發(fā)請(qǐng)求數(shù)為1000 
  3. ab -c 10000 -n 100000 http://172.16.0.20:80/ 
  4. This is ApacheBench, Version 2.3 <$Revision: 1430300 $> 
  5. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 
  6. Licensed to The Apache Software Foundation, http://www.apache.org/ 
  7.  
  8. Benchmarking 172.16.0.20 (be patient) 
  9. Completed 10000 requests 
  10. Completed 20000 requests 
  11. Completed 30000 requests 
  12. Completed 40000 requests 
  13. Completed 50000 requests 
  14. Completed 60000 requests 
  15. Completed 70000 requests 
  16. Completed 80000 requests 
  17. Completed 90000 requests 
  18. Completed 100000 requests 
  19. Finished 100000 requests 
  20.  
  21.  
  22. Server Software:        nginx/1.20.1 
  23. Server Hostname:       172.16.0.20 
  24. Server Port:            80 
  25.  
  26. Document Path:          / 
  27. Document Length:        4833 bytes 
  28.  
  29. Concurrency Level:      10000 
  30. Time taken for tests:   2.698 seconds 
  31. Complete requests:      100000 
  32. Failed requests:        167336 
  33.    (Connect: 0, Receive: 0, Length: 84384, Exceptions: 82952) 
  34. Write errors:           0 
  35. Total transferred:      86399264 bytes 
  36. HTML transferred:       82392984 bytes 
  37. Requests per second:    37069.19 [#/sec] (mean) 
  38. Time per request:       269.766 [ms] (mean) 
  39. Time per request:       0.027 [ms] (mean, across all concurrent requests) 
  40. Transfer rate:          31276.86 [Kbytes/sec] received 
  41.  
  42. Connection Times (ms) 
  43.               min  mean[+/-sd] median   max 
  44. Connect:        0  129 151.5    106    1144 
  45. Processing:    39  121  37.7    114     239 
  46. Waiting:        0   23  51.8      0     159 
  47. Total:        142  250 152.4    224    1346 
  48.  
  49. Percentage of the requests served within a certain time (ms) 
  50.   50%    224 
  51.   66%    227 
  52.   75%    232 
  53.   80%    236 
  54.   90%    283 
  55.   95%    299 
  56.   98%   1216 
  57.   99%   1228 
  58.  100%   1346 (longest request) 

其間共執(zhí)行了兩次 ss 命令,從上面的輸出結(jié)果,可以發(fā)現(xiàn)當(dāng)前 TCP 全連接隊(duì)列上升到了 512 大小,超過(guò)了最大 TCP 全連接隊(duì)列。

  1.  ss -tulnp|grep 80 
  2. tcp    LISTEN     411    511       *:80                    *:*                   users:(("nginx",pid=22913,fd=6),("nginx",pid=22912,fd=6),("nginx",pid=22911,fd=6)) 
  3. ss -tulnp|grep 80 
  4. tcp    LISTEN     512    511       *:80                    *:*                   users:(("nginx",pid=22913,fd=6),("nginx",pid=22912,fd=6),("nginx",pid=22911,fd=6)) 

當(dāng)超過(guò)了 TCP 最大全連接隊(duì)列,服務(wù)端則會(huì)丟掉后續(xù)進(jìn)來(lái)的 TCP 連接,丟掉的 TCP 連接的個(gè)數(shù)會(huì)被統(tǒng)計(jì)起來(lái),我們可以使用 netstat -s 命令來(lái)查看:

  1. netstat -s|grep overflowed 
  2.    1233972 times the listen queue of a socket overflowed 

上面看到的 1233972 times ,表示全連接隊(duì)列溢出的次數(shù),注意這個(gè)是累計(jì)值。可以隔幾秒鐘執(zhí)行下,如果這個(gè)數(shù)字一直在增加的話肯定全連接隊(duì)列滿了。

  1. netstat -s|grep overflowed 
  2.     1292022 times the listen queue of a socket overflowed 

從上面的模擬結(jié)果,可以得知,當(dāng)服務(wù)端并發(fā)處理大量請(qǐng)求時(shí),如果 TCP 全連接隊(duì)列過(guò)小,就容易溢出。發(fā)生 TCP 全連接隊(duì)列溢出的時(shí)候,后續(xù)的請(qǐng)求就會(huì)被丟棄,這樣就會(huì)出現(xiàn)服務(wù)端請(qǐng)求數(shù)量上不去的現(xiàn)象。

Linux 有個(gè)參數(shù)可以指定當(dāng) TCP 全連接隊(duì)列滿了會(huì)使用什么策略來(lái)回應(yīng)客戶端

實(shí)際上,丟棄連接只是 Linux 的默認(rèn)行為,我們還可以選擇向客戶端發(fā)送 RST 復(fù)位報(bào)文,告訴客戶端連接已經(jīng)建立失敗。

  1. $ cat /proc/sys/net/ipv4/tcp_abort_on_overflow 

tcp_abort_on_overflow 共有兩個(gè)值分別是 0 和 1,其分別表示:

  • 0 :如果全連接隊(duì)列滿了,那么 server 扔掉 client 發(fā)過(guò)來(lái)的 ack ;
  • 1 :如果全連接隊(duì)列滿了,server 發(fā)送一個(gè) reset 包給 client,表示廢掉這個(gè)握手過(guò)程和這個(gè)連接;

如果要想知道客戶端連接不上服務(wù)端,是不是服務(wù)端 TCP 全連接隊(duì)列滿的原因,那么可以把 tcp_abort_on_overflow 設(shè)置為 1,這時(shí)如果在客戶端異常中可以看到很多 connection reset by peer 的錯(cuò)誤,那么就可以證明是由于服務(wù)端 TCP 全連接隊(duì)列溢出的問(wèn)題。通常情況下,應(yīng)當(dāng)把 tcp_abort_on_overflow 設(shè)置為 0,因?yàn)檫@樣更有利于應(yīng)對(duì)突發(fā)流量。所以,tcp_abort_on_overflow 設(shè)為 0 可以提高連接建立的成功率,只有你非常肯定 TCP 全連接隊(duì)列會(huì)長(zhǎng)期溢出時(shí),才能設(shè)置為 1 以盡快通知客戶端。

  1. sysctl -w net.ipv4.tcp_abort_on_overflow = 0 

如何增大 TCP 全連接隊(duì)列呢?

根據(jù)上面提到的TCP 全連接隊(duì)列的最大值取決于 somaxconn 和 backlog 之間的最小值,也就是 min(somaxconn, backlog)。我們現(xiàn)在調(diào)整somaxconn值:

  1. $ sysctl -w net.core.somaxconn=65535 

調(diào)整nginx配置:

  1. server { 
  2.     listen  80  backlog=65535; 
  3.     ... 

最后要重啟 Nginx 服務(wù),因?yàn)橹挥兄匦抡{(diào)用 listen() 函數(shù) TCP 全連接隊(duì)列才會(huì)重新初始化。服務(wù)端執(zhí)行 ss 命令,查看 TCP 全連接隊(duì)列大小:

  1. $ ss -tulntp|grep 80 
  2. tcp    LISTEN     0       65535    *:80                    *:*                   users:(("nginx",pid=24212,fd=6),("nginx",pid=24211,fd=6),("nginx",pid=24210,fd=6)) 

從執(zhí)行結(jié)果,可以發(fā)現(xiàn) TCP 全連接最大值為 65535。

增大 TCP 全連接隊(duì)列后,繼續(xù)壓測(cè)

  1. ab -c 10000 -n 100000 http://172.16.0.20:80/ 
  2. This is ApacheBench, Version 2.3 <$Revision: 1430300 $> 
  3. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 
  4. Licensed to The Apache Software Foundation, http://www.apache.org/ 
  5.  
  6. Benchmarking 172.16.0.20 (be patient) 
  7. Completed 10000 requests 
  8. Completed 20000 requests 
  9. Completed 30000 requests 
  10. Completed 40000 requests 
  11. Completed 50000 requests 
  12. Completed 60000 requests 
  13. Completed 70000 requests 
  14. Completed 80000 requests 
  15. Completed 90000 requests 
  16. Completed 100000 requests 
  17. Finished 100000 requests 
  18.  
  19.  
  20. Server Software:        nginx/1.20.1 
  21. Server Hostname:        172.16.0.20 
  22. Server Port:            80 
  23.  
  24. Document Path:          / 
  25. Document Length:        4833 bytes 
  26.  
  27. Concurrency Level:      10000 
  28. Time taken for tests:   2.844 seconds 
  29. Complete requests:      100000 
  30. Failed requests:        178364 
  31.    (Connect: 0, Receive: 0, Length: 89728, Exceptions: 88636) 
  32. Write errors:           0 
  33. Total transferred:      57592752 bytes 
  34. HTML transferred:       54922212 bytes 
  35. Requests per second:    35159.35 [#/sec] (mean) 
  36. Time per request:       284.419 [ms] (mean) 
  37. Time per request:       0.028 [ms] (mean, across all concurrent requests) 
  38. Transfer rate:          19774.64 [Kbytes/sec] received 
  39.  
  40. Connection Times (ms) 
  41.               min  mean[+/-sd] median   max 
  42. Connect:        0  130  18.3    130     172 
  43. Processing:    45  142  40.1    138     281 
  44. Waiting:        0   19  52.4      0     185 
  45. Total:        159  272  31.2    272     390 
  46.  
  47. Percentage of the requests served within a certain time (ms) 
  48.   50%    272 
  49.   66%    274 
  50.   75%    275 
  51.   80%    276 
  52.   90%    280 
  53.   95%    358 
  54.   98%    370 
  55.   99%    375 
  56.  100%    390 (longest request) 

服務(wù)端執(zhí)行 ss 命令,查看 TCP 全連接隊(duì)列使用情況:

  1. $ ss -tulnp|grep 80 
  2. tcp    LISTEN     8      65535     *:80                    *:*                   users:(("nginx",pid=24212,fd=6),("nginx",pid=24211,fd=6),("nginx",pid=24210,fd=6)) 
  3. $ ss -tulnp|grep 80 
  4. tcp    LISTEN     352    65535     *:80                    *:*                   users:(("nginx",pid=24212,fd=6),("nginx",pid=24211,fd=6),("nginx",pid=24210,fd=6)) 
  5. $ ss -tulnp|grep 80 
  6. tcp    LISTEN     0      65535     *:80                    *:*                   users:(("nginx",pid=24212,fd=6),("nginx",pid=24211,fd=6),("nginx",pid=24210,fd=6)) 

從上面的執(zhí)行結(jié)果,可以發(fā)現(xiàn)全連接隊(duì)列使用增長(zhǎng)的很快,但是一直都沒有超過(guò)最大值,所以就不會(huì)溢出,那么 netstat -s 就不會(huì)有 TCP 全連接隊(duì)列溢出個(gè)數(shù)繼續(xù)增加:

  1. $ netstat -s|grep overflowed 
  2.     1540879 times the listen queue of a socket overflowed 
  3. $ netstat -s|grep overflowed 
  4.     1540879 times the listen queue of a socket overflowed 
  5. $ netstat -s|grep overflowed 
  6.     1540879 times the listen queue of a socket overflowed 
  7. $ netstat -s|grep overflowed 
  8.     1540879 times the listen queue of a socket overflowed 

說(shuō)明 TCP 全連接隊(duì)列最大值從 512 增大到 65535 后,服務(wù)端抗住了 10 萬(wàn)連接并發(fā)請(qǐng)求,也沒有發(fā)生全連接隊(duì)列溢出的現(xiàn)象了。如果持續(xù)不斷地有連接因?yàn)?TCP 全連接隊(duì)列溢出被丟棄,就應(yīng)該調(diào)大 backlog 以及 somaxconn 參數(shù)。

TCP四次揮手

  • 第一次揮手:主動(dòng)關(guān)閉方發(fā)送一個(gè)FIN,用來(lái)關(guān)閉主動(dòng)方到被動(dòng)關(guān)閉方的數(shù)據(jù)傳送,也就是主動(dòng)關(guān)閉方告訴被動(dòng)關(guān)閉方:我已經(jīng)不會(huì)再給你發(fā)數(shù)據(jù)了(當(dāng)然,在fin包之前發(fā)送出去的數(shù)據(jù),如果沒有收到對(duì)應(yīng)的ack確認(rèn)報(bào)文,主動(dòng)關(guān)閉方依然會(huì)重發(fā)這些數(shù)據(jù)),但此時(shí)主動(dòng)關(guān)閉方還可以接受數(shù)據(jù)。
  • 第二次揮手:被動(dòng)關(guān)閉方收到FIN包后,發(fā)送一個(gè)ACK給對(duì)方,確認(rèn)序號(hào)為收到序號(hào)+1(與SYN相同,一個(gè)FIN占用一個(gè)序號(hào))。
  • 第三次揮手:被動(dòng)關(guān)閉方發(fā)送一個(gè)FIN,用來(lái)關(guān)閉被動(dòng)關(guān)閉方到主動(dòng)關(guān)閉方的數(shù)據(jù)傳送,也就是告訴主動(dòng)關(guān)閉方,我的數(shù)據(jù)也發(fā)送完了,不會(huì)再給你發(fā)數(shù)據(jù)了。
  • 第四次揮手:主動(dòng)關(guān)閉方收到FIN后,發(fā)送一個(gè)ACK給被動(dòng)關(guān)閉方,確認(rèn)序號(hào)為收到序號(hào)+1,至此,完成四次揮手。

互聯(lián)網(wǎng)中往往服務(wù)器才是主動(dòng)關(guān)閉連接的一方。這是因?yàn)椋琀TTP 消息是單向傳輸協(xié)議,服務(wù)器接收完請(qǐng)求才能生成響應(yīng),發(fā)送完響應(yīng)后就會(huì)立刻關(guān)閉 TCP 連接,這樣及時(shí)釋放了資源,能夠?yàn)楦嗟挠脩舴?wù)。

四次揮手的狀態(tài)

我們來(lái)看斷開連接的時(shí)候的狀態(tài)時(shí)序圖:

其實(shí)四次揮手只涉及兩種報(bào)文:FIN 和 ACK。FIN 就是 Finish 結(jié)束連接的意思,誰(shuí)發(fā)出 FIN 報(bào)文,就表示它將不再發(fā)送任何數(shù)據(jù),關(guān)閉這一方向的傳輸通道。ACK 是 Acknowledge 確認(rèn)的意思,它用來(lái)通知對(duì)方,你方的發(fā)送通道已經(jīng)關(guān)閉。

  • 當(dāng)主動(dòng)方關(guān)閉連接時(shí),會(huì)發(fā)送 FIN 報(bào)文,此時(shí)主動(dòng)方的連接狀態(tài)由 ESTABLISHED 變?yōu)?FIN_WAIT1。
  • 當(dāng)被動(dòng)方收到 FIN 報(bào)文后,內(nèi)核自動(dòng)回復(fù) ACK 報(bào)文,連接狀態(tài)由 ESTABLISHED 變?yōu)?CLOSE_WAIT,顧名思義,它在等待進(jìn)程調(diào)用 close 函數(shù)關(guān)閉連接。
  • 當(dāng)主動(dòng)方接收到這個(gè) ACK 報(bào)文后,連接狀態(tài)由 FIN_WAIT1 變?yōu)?FIN_WAIT2,主動(dòng)方的發(fā)送通道就關(guān)閉了。
  • 當(dāng)被動(dòng)方進(jìn)入 CLOSE_WAIT 狀態(tài)時(shí),進(jìn)程的 read 函數(shù)會(huì)返回 0,這樣開發(fā)人員就會(huì)有針對(duì)性地調(diào)用 close 函數(shù),進(jìn)而觸發(fā)內(nèi)核發(fā)送 FIN 報(bào)文,此時(shí)被動(dòng)方連接的狀態(tài)變?yōu)?LAST_ACK。當(dāng)主動(dòng)方收到這個(gè) FIN 報(bào)文時(shí),內(nèi)核會(huì)自動(dòng)回復(fù) ACK,同時(shí)連接的狀態(tài)由 FIN_WAIT2 變?yōu)? TIME_WAIT,Linux 系統(tǒng)下等待的時(shí)間設(shè)為 2MSL,MSL 是 Maximum Segment Lifetime,報(bào)文最大生存時(shí)間,它是任何報(bào)文在網(wǎng)絡(luò)上存在的最長(zhǎng)時(shí)間,超過(guò)這個(gè)時(shí)間報(bào)文將被丟棄。TIME_WAIT 狀態(tài)的連接才會(huì)徹底關(guān)閉。

當(dāng)被動(dòng)方收到 ACK 報(bào)文后,連接就會(huì)關(guān)閉。

主動(dòng)方TIME_WAIT優(yōu)化

大量處于 TIME_WAIT 狀態(tài)的連接,它們會(huì)占用大量?jī)?nèi)存和端口資源。這時(shí),我們可以優(yōu)化與 TIME_WAIT 狀態(tài)相關(guān)的內(nèi)核選項(xiàng),比如采取下面幾種措施。

  • 增大處于 TIME_WAIT 狀態(tài)的連接數(shù)量 net.ipv4.tcp_max_tw_buckets ,并增大連接跟蹤表的大小 net.netfilter.nf_conntrack_max。
  1. sysctl -w net.ipv4.tcp_max_tw_buckets=1048576 
  2. sysctl -w net.netfilter.nf_conntrack_max=1048576 
  • 減小FIN_WAIT2狀態(tài)的參數(shù) net.ipv4.tcp_fin_timeout 的時(shí)間和減小TIME_WAIT 狀態(tài)的參數(shù)net.netfilter.nf_conntrack_tcp_timeout_time_wait的時(shí)間 ,讓系統(tǒng)盡快釋放它們所占用的資源。
  1. sysctl -w net.ipv4.tcp_fin_timeout=15 
  2. sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30 
  • 開啟端口復(fù)用 net.ipv4.tcp_tw_reuse。這樣,被 TIME_WAIT 狀態(tài)占用的端口,還能用到新建的連接中。
  1. sysctl -w net.ipv4.tcp_tw_reuse=1 
  • 增大本地端口的范圍 net.ipv4.ip_local_port_range 。這樣就可以支持更多連接,提高整體的并發(fā)能力。
  1. sysctl -w net.ipv4.ip_local_port_range="1024 65535" 
  • 增加最大文件描述符的數(shù)量。你可以使用 fs.nr_open 和 fs.file-max ,分別增大進(jìn)程和系統(tǒng)的最大文件描述符數(shù);或在應(yīng)用程序的 systemd 配置文件中,配置 LimitNOFILE ,設(shè)置應(yīng)用程序的最大文件描述符數(shù)。
  1. sysctl -w fs.nr_open=1048576 
  2. sysctl -w fs.file-max=1048576 

巨人的肩膀

[1] 系統(tǒng)性能調(diào)優(yōu)必知必會(huì).陶輝.極客時(shí)間.

[2] TCP/IP詳解卷二:實(shí)現(xiàn)

本文轉(zhuǎn)載自微信公眾號(hào)「 運(yùn)維開發(fā)故事」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系 運(yùn)維開發(fā)故事公眾號(hào)。

【編輯推薦】

【責(zé)任編輯:姜華 TEL:(010)68476606】
責(zé)任編輯:姜華 來(lái)源: 運(yùn)維開發(fā)故事
相關(guān)推薦

2024-01-12 08:23:11

TCPACK服務(wù)器

2015-10-13 09:42:52

TCP網(wǎng)絡(luò)協(xié)議

2019-06-12 11:26:37

TCP三次握手四次揮手

2023-10-24 15:22:09

TCPUDP

2020-02-17 10:10:43

TCP三次握手四次揮手

2021-07-03 17:47:25

TCP控制協(xié)議

2021-01-29 06:11:08

TCP通信三次握手

2021-05-18 12:27:40

TCP控制協(xié)議

2019-02-01 09:38:16

2015-11-09 09:58:56

2014-09-19 09:46:46

TCPIP

2017-09-25 21:27:07

TCP協(xié)議數(shù)據(jù)鏈

2021-05-28 09:08:20

TCP連接序列號(hào)

2020-06-29 14:50:47

TCP狀態(tài)ACK

2025-05-20 08:38:03

2023-10-28 09:07:57

TCP面試三次握手

2022-11-17 10:20:49

TCP三次握手四次揮手

2020-03-02 14:41:04

運(yùn)維架構(gòu)技術(shù)

2023-10-17 15:44:19

TCP四次揮手

2023-11-01 08:04:08

WiresharkTCP協(xié)議
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 久久久日韩精品一区二区三区 | 亚洲午夜网 | 亚洲精品久久久久久国产精华液 | 国产高清精品一区二区三区 | 亚洲视频一区在线 | 欧美aⅴ在线观看 | 亚洲精品视频在线 | 精品少妇一区二区三区日产乱码 | 国产精品一区一区三区 | 久草色播 | 亚洲国产成人精品女人久久久 | 久久1区 | 午夜国产一级 | 成人免费毛片片v | 国产精品视频不卡 | 亚洲精品在线免费播放 | 在线一区视频 | 中文字幕国产在线 | 久久九精品 | 亚洲欧美激情精品一区二区 | 久久久久久国产精品 | 成人精品免费视频 | 国产婷婷精品av在线 | 少妇一区在线观看 | 日韩乱码一二三 | 久久成 | 成人影视网址 | 欧美日韩高清免费 | 一区二区三区视频在线观看 | 国产一级淫片a直接免费看 免费a网站 | 国产专区在线 | 一区观看| 91tv在线观看 | 亚洲 欧美 综合 | 伦理片97| 二区中文| 91影视| 91精品久久久久久久久久入口 | 成人高清在线 | 98久久| 中文字幕视频在线看5 |