問題描述:
線上環境有多個實例,分別在不同的機房。正常情況下沒問題,但每當同機房下,添加新的實例服務器後,在這臺新的實例上就會偶發出現請求超時或無響應的情況。併發量越大,出現的概率越高。ping正常。curl或正常http請求時,就會偶發出現該問題。
故障定位
首先,梳理網絡流程。服務器在訪問公網地址時,會經過nat網關轉換到公網的地址,然後再去訪問目標地址。
其次,分別在服務器,nat服務器,目標服務器通過tcpdump抓包。通過分析出現問題時的數據包發現,服務器,nat服務器都是隻有發送的syn包,而沒有收到目標服務返回的ack確認包。由於沒有收到ack確認包,服務器一直重試發送syn包。
最後,通過調研內核參數,發現參數net.ipv4.tcp_timestamps用來校驗同源公網Ip的時間戳。經過nat之後,如果前面相同的端口被使用過,且時間戳大於這個鏈接發出的syn中的時間戳,服務器上就會忽略掉這個syn,不返會syn-ack消息,表現爲用戶無法正常完成tcp 3次握手,導致連接超時或無響應。
在業務閒時,如果用戶nat的端口沒有被使用過時,就可以正常打開;業務忙時,nat端口重複使用的頻率高,很難分到沒有被使用的端口,從而產生這種問題。
解決方案
net.ipv4.tcp_timestamps 默認值爲1,即開啓時間戳的校驗。並且只有客戶端服務和服務端都開啓時,纔會出現該問題。
於是,將服務端的net.ipv4.tcp_timestamps設置爲0後,解決該問題。