graceful restart server 微服務(wù)架構(gòu)中無(wú)縫重啟某個(gè)服務(wù)

背景

我們的服務(wù)器大致架構(gòu)是一個(gè)接入服mixer,mixer會(huì)連后臺(tái)的服務(wù)backend,兩者之間通過(guò)GRPC通信(長(zhǎng)連接)。backend可能有多實(shí)例,所以為了負(fù)載均衡,mixer維護(hù)了一個(gè)連接池,連接池會(huì)定期進(jìn)行刷新(2min一次)。

問(wèn)題

當(dāng)某一個(gè)backend實(shí)例重啟時(shí),mixer并不能立即感知到,而要等到下一次刷新連接池才會(huì)更新連接。這樣在backend重啟到mixer下次刷新期間的請(qǐng)求如果被路由到正在重啟的backend實(shí)例,就會(huì)一直等到超時(shí)返回。

解決

我們是通過(guò)kubernetes管理服務(wù),backend重啟時(shí),k8s會(huì)先啟動(dòng)一個(gè)新的實(shí)例,等新的實(shí)例ready for serve,就發(fā)送SIGTERM給舊的實(shí)例。在接收到SIGTERM后,backend就進(jìn)入關(guān)閉過(guò)程,這時(shí)是無(wú)法保證正常返回的。
所以在backend程序中加了對(duì)系統(tǒng)SIGTERM信號(hào)的處理:當(dāng)接收到SIGTERM信號(hào),會(huì)設(shè)置一個(gè)全局變量為true,標(biāo)識(shí)服務(wù)器正在關(guān)閉中。當(dāng)其他線程接收到mixer的信號(hào),會(huì)去讀這個(gè)全局變量,發(fā)現(xiàn)自己已經(jīng)在關(guān)閉過(guò)程中,就會(huì)給mixer返回一個(gè)特定的消息。
那么mixer接收到這個(gè)消息應(yīng)該如何做呢?
1)接收到這個(gè)消息代表某個(gè)backend實(shí)例即將失效,應(yīng)該對(duì)連接池中所有指向這個(gè)實(shí)例的連接進(jìn)行刷新。
2)接收到這個(gè)消息的請(qǐng)求應(yīng)該換一個(gè)有效的連接進(jìn)行重試。
但是這里有個(gè)問(wèn)題就是我們用的是GRPC,進(jìn)行連接的是一個(gè)k8s service的地址,而不是每個(gè)instance的真實(shí)地址,所以我們維護(hù)的連接池中的連接,是不知道自己連向哪一個(gè)backend實(shí)例的,所以1)和2)都會(huì)有問(wèn)題,如下:
1)無(wú)法區(qū)分哪些連接是指向即將關(guān)閉的實(shí)例,所以就無(wú)法確定該刷新哪些連接。
2)無(wú)法知道哪個(gè)連接是指向即將關(guān)閉的實(shí)例,所以無(wú)法選出有效的連接。

針對(duì)1),最簡(jiǎn)單的辦法就是在收到SIGTERM時(shí)刷新全部連接,但代價(jià)太高,會(huì)阻塞mixer的全部服務(wù)。
針對(duì)2),如何選到一個(gè)有效的連接呢?由于待重啟的實(shí)例在接收到SIGTERM信號(hào)時(shí),k8s已經(jīng)將其從service的列表中摘除,那么刷新后的連接就肯定不是連向即將關(guān)閉的實(shí)例,問(wèn)題解決。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容