咱們這邊是一個基於Nginx的API網關(如下標記爲A),最近兩天有調用方反饋,偶爾會出現502錯誤,咱們從Nginx的error日誌裏看,就會發現有" upstream prematurely closed connection while reading response header from upstream"這麼一條錯誤日誌,翻譯過來其實就是上游服務過早的關閉了鏈接,意思很清楚,可是爲何會出現這種狀況呢。並且是在業務低峯出現這種狀況(也只是小几率的出現),在業務高峯的時候沒有出現這種狀況,並且上游服務方(如下標記爲B)說出問題的請求他們那邊沒有收到,也就是沒有任何記錄,這就比較詭異了。測試環境不知道如何去復現,也就很差排查。nginx
一、在服務器上開啓tcpdump抓包 tcpdump -nps0 -iany -w /tmp/20180617.pcap net [ip] and net [ip],若是不知道tcpdump怎麼使用的同窗能夠百度一下。服務器
二、在nginx的error.log中觀察到到有兩條" upstream prematurely closed connection while reading response header from upstream"錯誤日誌,分別是2018/06/07 20:41:27和2018/06/08 09:10:46兩個時間點,以下圖網絡
三、而後查看抓包數據,找到了對應時間點的包數據,從這個能夠看出,A向B發送了一個1060-2143的包,,而服務端發送了一個Fin斷開鏈接。爲何服務端會斷開鏈接了,咱們不得而知。併發
四、上一步A發送包首字節數是1060,那必然前面確定發送過包,那咱們繼續往上查,發現了以下圖所示的現象。在20:40:22的時候3次握手創建鏈接併發送了第一個包;並且也查了在20:40:22到20:41:27中間這條長鏈接沒有發送任何包tcp
五、和B溝通,他們的Nginx中的keepalive_timeout配置爲65秒,keepalive_timeout這個配置的意思是說長鏈接保持的時間,若是沒有任何數據傳輸的話,超過這個時間,服務端會關閉這個鏈接。那這就對上了,說明在這65秒沒有任何數據傳輸,也正好在這個點,A向B發送了數據,而B關閉了這個鏈接,因而就出現了上面的現象。測試
六、固然這是我根據抓包分析出來的結果,我也本身模擬了這種狀況,寫了一個定時任務,每隔一分鐘向第一臺nginx發送請求,轉發到第二臺nginx上。第二臺nginx的keepalive_timeout配置爲60,在發送第七次的時候,出現了一樣的問題,nginx打印一樣的錯誤日誌,抓包的結果也和上述狀況一致。驗證了我上述的分析過程。翻譯
一、若是系統併發量不大,沒有必要開啓長鏈接,有兩種方式,1、第一臺nginx能夠去除proxy_http_version 1.1; proxy_set_header Connection "0";這兩個配置;2、第二臺nginx的keepalive_timeout能夠配置爲0(默認是75)。日誌
二、上述問題個人解決方案是:暫時調大keepalive_timeout的值,先觀察,但頗有可能仍是會有這個問題。blog
一、網絡問題的排查過程是很痛苦了,再一次驗證了基礎知識的重要性。ip
二、偶然報出的問題,必定不要忽視,說不定之後就是系統的瓶頸。