1. 程式人生 > 其它 >調整 net.ipv4.tcp_tw_recycle 造成的故障

調整 net.ipv4.tcp_tw_recycle 造成的故障

  • 背景

在 nat 的網路環境訪問伺服器時會有不定時連線超時的問題

  • 原因

出現此問題,可能是系統引數設定問題,即以下兩個引數都設定為 1

1
2
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_recycle = 1

RFC1323中有如下一段描述:

An additional mechanism could be added to the TCP, a per-host cache of the last timestamp received from any connection. This value could then be used in the PAWS mechanism to reject old duplicate segments from earlier incarnations of the connection, if the timestamp clock can be guaranteed to have ticked at least once since the old connection was open. This would require that the TIME-WAIT delay plus the RTT together must be at least one tick of the sender’s timestamp clock. Such an extension is not part of the proposal of this RFC.

大概意思是說TCP有一種行為,可以快取每個主機最新的時間戳,後續請求中如果時間戳小於快取的時間戳,即視為無效,相應的資料包會被丟棄。

Linux是否啟用這種行為取決於tcp_timestamps和tcp_tw_recycle,因為tcp_timestamps預設就是開啟的,所以當tcp_tw_recycle被開啟後,實際上這種行為就被激活了,當客戶端或服務端以NAT方式構建的時候就可能出現問題,下面以客戶端NAT為例來說明:

當多個客戶端通過NAT方式聯網並與服務端互動時,服務端看到的是同一個IP,也就是說對服務端而言這些客戶端實際上等同於一個,可惜由於這些客戶端的時間戳可能存在差異,於是乎從服務端的視角看,便可能出現時間戳錯亂的現象,進而直接導致時間戳小的資料包被丟棄。如果發生了此類問題,具體的表現通常是是客戶端明明發送的SYN,但服務端就是不響應ACK,我們可以通過下面命令來確認資料包不斷被丟棄的現象:

1
2
shell> netstat -s | grep timestamp
... packets rejects in established connections because of timestamp

安全起見,通常要禁止tcp_tw_recycle。說到這裡,大家可能會想到另一種解決方案:把tcp_timestamps設定為0,tcp_tw_recycle設定為1,這樣不就可以魚與熊掌兼得了麼?可惜一旦關閉了tcp_timestamps,那麼即便打開了tcp_tw_recycle,也沒有效果。

引用地址:https://huoding.com/2012/01/19/142

  • 解決辦法

    解決的方法就是將這兩個引數修改為:

    1
    2
    net.ipv4.tcp_timestamps = 1
    net.ipv4.tcp_tw_recycle = 0
  • 遇到的問題

    本來修改完成後再次請求就沒有問題了,但如果是 docker 伺服器的話,會發現容器中無法連線網路!

    因為修改net.ipv4.tcp_tw_recycle影響的是 nat 相關,所以如果容器是以 nat 方式上網的話,就會造成影響

  • 解決辦法

    解決以上問題,需要先停掉 docker 主程序,然後修改引數,再啟動

-