正常情況tcp四層握手關閉連接,rst基本都是異常情況,整理如下:
1. GFW
2. 對方端口未打開,發生在連接建立
如果端口打開,只是sync_backlog滿了的話,sync簡單被丟棄,表現為超時,而不會rst。
3. close Socket 時recv buffer 不為空
例如,客戶端發了兩個請求,服務器只從buffer 讀取第一個請求處理完就關閉連接,tcp層認為數據沒有正確提交到應用,使用rst關閉連接。
3. 移動鏈路
移動網絡下,國內是有5分鍾后就回收信令,也就是IM產品,如果心跳>5分鍾后服務器再給客戶端發消息,就會收到rst。也要查移動網絡下IM 保持<5min 心跳。
4. 負載等設備
負載設備需要維護連接轉發策略,長時間無流量,連接也會被清除,而且很多都不告訴兩層機器,新的包過來時才通告rst。
Apple push 服務也有這個問題,而且是不可預期的偶發性連接被rst;rst 前第一個消息write 是成功的,而第二條寫才會告訴你連接被重置,
曾經被它折騰沒轍,因此打開每2秒一次tcp keepalive,固定5分鍾tcp連接回收,而且發現連接出錯時,重發之前10s內消息。
5. SO_LINGER
同第三條,默認SO_LINGER選項關閉, 直接丟棄未發送完畢的send buffer,並發送rst,業務上表示為對端數據未收到;建議打開,但在linger time 內仍然未將buffer發送完,那依然發送rst。
好像曾經測試過haproxy 某種配置下,會使用rst關閉連接,少了網絡交互而且沒有 TIME_WAIT 問題
6. 超過超時重傳次數、網絡暫時不可達
7. TIME_WAIT 狀態
tw_recycle = 1 時,sync timestamps 比上次小時,會被rst
7. 設置 connect_timeout
應用設置了連接超時,sync 未完成時超時了,會發送rst終止連接。
8. 非正常包
連接已經關閉,seq 不正確等
9. keepalive 超時
公網服務tcp keepalive 最好別打開;移動網絡下會增加網絡負擔,切容易掉線;非移動網絡核心ISP設備也不一定都支持keepalive,曾經也發現過廣州那邊有個核心節點就不支持。
10. 待整理...
參考: