有報障,說是連接超時。。。然后查看docker里有隊列溢出
netstat -s | grep overflowed
通過抓取隊列溢出的大小,發現每次報障時,實例的隊列溢出數都會突增。
隊列溢出是查看現有連接數是否大於backlog,如果大於就丟棄,並overflow數+1,backlog數是有配置的backlog和系統的somaxconn決定的,backlog值取min(somaxconn,backlog)。
1.redis的配置文件有tcp-backlog,默認的是511
tcp服務里面默認有兩個隊列,一個是tcp-backlog,用於存放未連接隊列,另外一個是somaxconn,用於存放已連接隊列。
在完成tcp三次握手之前,首先進入未連接隊列,完成tcp三次握手之后正式建立連接,進入已連接隊列。因為redis是單進程的,如果主進程出現慢查詢的話,會導致已連接隊列堆滿,並且新accept的連接不能被處理,不能進入到已連接隊列,也導致未連接隊列堆滿,在服務器看到處於未連接隊列中的連接狀態為SYN_RECV。 新進來的客戶端連接將會一直處於SYN_SENT狀態等待服務器的ACK應答,最終導致連接超時。
關於TCP三次握手
-
- 第一次握手:建立連接時,客戶端發送syn包(syn=j)到服務器,並進入SYN_SEND狀態,等待服務器確認;
- 第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器 進入SYN_RECV狀態; 第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入 ESTABLISHED狀態,完成三次握手。 完成三次握手,客戶端與服務器開始傳送數據.
處理方法:將配置tcp-backlog設和系統somaxconn設置成8192