這里分享一個案例,問題的?原因是反向代理使用不當。
現象
首先描述一下問題的現象。當時的問題是應用啟動失敗,日志里面報錯顯示端口占用。我們的應用都是通過腳本發布的,之前發布過多次都沒有出現過問題。那么同樣的腳本、同樣的機器,這次怎么就發布失敗了呢?
報錯信息如下:
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和后端應用部署在同一臺機器。會有一定幾率導致后端應用的端口被占用。