問題現象
在某個時刻,后端收到了平時4-6倍的請求(保密起見,略去產品和事件),在10分鍾后居然沒有請求可以接進來
問題原因
經過分析,首先,是后端服務器的線程池滿了,線程池滿的原因:
1.server.xml中maxThread=512,導致超過512的之后的請求只能排隊,等待有線程釋放后,才能被處理;
2.connectionTimeout配置為10000,這個配置導致建立一個socket連接后,如果一直沒有收到客戶端的FIN,也沒有數據過來,那么此連接也必須等到10s后,才能被超時釋放,巧了,現網的客戶端真的不會發FIN包過來,那一直陪它耗夠10秒,和1一起,處理的512個線程只能等待10s后,超時釋放才能處理后面排隊的請求,所以浪涌一來,分分鍾就滿了。
接下來是怎么接不進來的呢?
部分用戶忍不了了,發了個登出請求,依然在特慢的排隊,部分進入了隊列的客戶端加上前面時間一共等了幾秒都沒響應,客戶端就發了個FIN過來,說要不咱主動斷開算了,后端收到請求變為CLOSE_WAIT狀態,說你等我會,處理點事,巧了,用戶這幾秒也受不了了,整個重啟客戶端,客戶端ip再來就變了,結果后端處理好后的第三次握手本該通知"我處理好了,你斷吧"的請求發不過去,好死不死,后台還配的重發15次,重發15次需要大概20~30分鍾左右,啊哦,於是這條請求一直占着線程20多分鍾,這樣的請求多點,線程就一直占着,於是別的請求就一直就接不進來咯
問題解決
1.修改maxThread=1024,提高一倍的線程數
2.修改connectionTimeout=2000,沒數據了之后2秒就斷,別等這么久(keepAlivetimeout是請求處理完了之后等多久關閉連接,connectionTimeout是本條連接等多久沒數據關連接)
3.修改/proc/sys/net/ipv4/目錄下的tcp_retries2文件為4,別重發15次了,一般也用不了這么多