這裏分享一個案例,問題的原因是反向代理使用不當。
現象
首先描述一下問題的現象。當時的問題是應用啓動失敗,日誌裏面報錯顯示端口占用。我們的應用都是通過腳本發佈的,之前發佈過多次都沒有出現過問題。那麼同樣的腳本、同樣的機器,這次怎麼就發佈失敗了呢?
報錯信息如下:
OSError: [Errno 48] Address already in use
問題排查
這個報錯是很常見的,以爲是發佈的過程中上一個應用沒有正常關閉。然後熟練的打開終端,連接到服務器,通過netstat -ant|grep LISTEN命令檢查這個端口被誰佔用了。這條命令的輸出如下:
tcp 0 0 0.0.0.0:53130 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:39308 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:46429 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:2049 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:51329 0.0.0.0:* LISTEN
tcp6 0 0 0.0.0.0:2280 :::* LISTEN
我們的服務使用8080端口。於是熟練的在輸出的內容裏尋找8080。可是並沒有找到!
看來這次情況跟以往不太一樣了。怎麼會這樣呢?既然沒有端口占用,爲什麼應用會起不來?於是我再次嘗試啓動應用,還是報了相同的錯誤。
轉機
既然這樣,那麼我直接搜索8080試試,於是輸入了下面的命令:
netstat -ant | grep 8080
很快,得到了下面的結果:
tcp 0 0 192.168.6.55:59580 192.168.6.55:8080 TIME_WAIT
居然出現了TIME_WAIT。在我的三觀裏TIME_WAIT只會出現在斷開連接的時候啊,監聽端口是不會出現TIME_WAIT的。這是要打破三觀的節奏嗎?
真相
真相只有一個。我讓運維借用sudo權限看看這個連接是哪個進程的。最後發現這個端口是被nginx佔用的。原來,nginx接收了很多請求,進行代理的時候發起tcp連接,這時會佔用一個未被使用的隨機端口。而後端應用和nginx部署在同一臺機器,由於請求過多,nginx發起了大量連接,每個連接都是短連接,佔用了大量的隨機端口,並且需要經過30秒的TIME_WAIT狀態才能釋放佔用。碰巧把後端應用的8080端口也佔用了,導致應用無法啓動。
結論
不要把nginx和後端應用部署在同一臺機器。會有一定機率導致後端應用的端口被佔用。