1 回答

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