1 回答

TA貢獻(xiàn)1816條經(jīng)驗(yàn) 獲得超6個贊
這不僅僅是 Go 的問題,但總的來說,我們可以將問題分為兩個獨(dú)立的問題:
確保當(dāng)前請求不會被終止并影響用戶體驗(yàn)。
確保沒有無法處理新請求的停機(jī)時間。
第一個更容易解決:你只是不要猛烈地殺死你的服務(wù)器,而是告訴它退出,導(dǎo)致“排水階段”,在這個階段它不接受新請求,只完成當(dāng)前正在運(yùn)行的請求,然后退出。例如,這可以通過偵聽信號并將應(yīng)用程序進(jìn)入特殊狀態(tài)來完成。
Go 并不簡單,因?yàn)槟J(rèn)的 http 服務(wù)器不支持關(guān)閉它,但是您可以使用 啟動服務(wù)器net.Listener
,然后保留對它的引用并在時間到期時關(guān)閉它。
現(xiàn)在,只執(zhí)行一種方法然后再次啟動服務(wù)將導(dǎo)致在此過程中不接受新請求,我們都知道在極端情況下這可能需要幾秒鐘。
所以我們需要的是另一個已經(jīng)運(yùn)行新代碼的服務(wù)器實(shí)例,在舊代碼沒有響應(yīng)新請求的那一刻,對吧?這可以通過多種方式完成:
擁有多個服務(wù)器,并且在它們之上有一個負(fù)載平衡器,允許一個(或多個)服務(wù)器在我們重新啟動另一臺服務(wù)器時承擔(dān)負(fù)載。這是最簡單的方法,也是大多數(shù)人的做法。如果您需要 N 個服務(wù)器來承擔(dān)您的用戶的負(fù)載,只需保留 N+1 并一次重新啟動一個。
使用套接字共享技巧。在較新的 Linux 內(nèi)核中,許多進(jìn)程可以在同一個端口上偵聽和接受。您所做的只是啟動新實(shí)例,然后告訴舊實(shí)例完成并退出。這樣就沒有停頓。這是通過設(shè)置
SO_REUSEPORT
偵聽套接字來完成的。以上可以通過準(zhǔn)備交付的解決方案自動化,例如 Einhorn,為您處理所有細(xì)節(jié),請參閱https://github.com/stripe/einhorn
這篇博文中記錄了另一種方法:http : //blog.nella.org/?p=879
- 1 回答
- 0 關(guān)注
- 306 瀏覽
添加回答
舉報