Dubbo - Go 優(yōu)雅上下線設(shè)計(jì)與實(shí)踐
一 背景
1 優(yōu)雅上下線
在分布式場(chǎng)景下,微服務(wù)進(jìn)程都是以容器的形式存在,在容器調(diào)度系統(tǒng)例如 k8s 的支持下運(yùn)行,容器組 Pod 是 K8S 的最小資源單位。隨著服務(wù)的迭代和更新,當(dāng)新版本上線后,需要針對(duì)線上正在運(yùn)行的服務(wù)進(jìn)行替換,從而發(fā)布新版本。
在穩(wěn)定生產(chǎn)的過程中,容器調(diào)度完全由 k8s 管控,微服務(wù)治理由服務(wù)框架或者運(yùn)維人員進(jìn)行維護(hù)和管理。而在發(fā)布新版本,或者擴(kuò)縮容的場(chǎng)景下,會(huì)終止舊的容器實(shí)例,并使用新的容器實(shí)例進(jìn)行替換,對(duì)于承載高流量的線上生產(chǎn)環(huán)境,這個(gè)替換過程的銜接一但出現(xiàn)問題,將在短時(shí)間內(nèi)造成大量的錯(cuò)誤請(qǐng)求,觸發(fā)報(bào)警甚至影響正常業(yè)務(wù)。對(duì)于體量較大的廠家,發(fā)布過程出現(xiàn)問題所造成的損失會(huì)是巨大的。
因此,優(yōu)雅上下線的訴求被提出。這要求服務(wù)框架在擁有穩(wěn)定服務(wù)調(diào)用能力,傳統(tǒng)服務(wù)治理能力的基礎(chǔ)之上,應(yīng)當(dāng)提供服務(wù)上下線過程中穩(wěn)定的保障,從而減少運(yùn)維成本,提高應(yīng)用穩(wěn)定性。
2 期望效果
我認(rèn)為,理想狀態(tài)下優(yōu)雅上下線的效果,是在一個(gè)承載大量流量的分布式系統(tǒng)內(nèi),所有組件實(shí)例都可以隨意地?cái)U(kuò)容、縮容、滾動(dòng)更新,在這種情況下需要保證更新過程中穩(wěn)定的 tps (每秒請(qǐng)求數(shù)) 和 rt(請(qǐng)求時(shí)延),并且保證不因?yàn)樯舷戮€造成請(qǐng)求錯(cuò)誤。再深一步,就是系統(tǒng)的容災(zāi)能力,在一個(gè)或多個(gè)節(jié)點(diǎn)不可用的情況下,能保證流量的合理調(diào)度,從而盡最大能力減少錯(cuò)誤請(qǐng)求的出現(xiàn)。
- Dubbo-go 的優(yōu)雅上下線能力
Dubbo-go 對(duì)優(yōu)雅上下線的探究可以追溯到三年前,早在1.5早期版本,Dubbo-go 就已經(jīng)擁有優(yōu)雅下線能力。通過對(duì)終止信號(hào)量的監(jiān)聽,實(shí)現(xiàn)反注冊(cè)、端口釋放等善后工作,摘除流量,保證客戶端請(qǐng)求的正確響應(yīng)。
在前一段時(shí)間,隨著 Dubbo-go 3.0 的正式發(fā)版,我在一條 proposal issue (dubbo-go issue 1685) [1] 中提到了一些生產(chǎn)用戶比較看重的問題,作為 3.x 版本的發(fā)力方向,并邀請(qǐng)大家談?wù)搶?duì)這些方向的看法,其中用戶呼聲最高的特性就是無損上下線的能力,再次感謝社區(qū)的王曉偉同學(xué)的貢獻(xiàn)。
經(jīng)過不斷完善和生產(chǎn)環(huán)境測(cè)試,目前 Dubbo-go 已擁有該能力,將在后續(xù)版本中正式與大家見面。
二 Dubbo-go 優(yōu)雅上下線實(shí)現(xiàn)思路
優(yōu)雅上下線可以分為三個(gè)角度。服務(wù)端的上線,服務(wù)端的下線,和客戶端的容災(zāi)策略。這三個(gè)角度,保證了生產(chǎn)實(shí)例在正常的發(fā)布迭代中,不出現(xiàn)錯(cuò)誤請(qǐng)求。
1 客戶端負(fù)載均衡機(jī)制
以 Apache 頂級(jí)項(xiàng)目 Dubbo 為典范的微服務(wù)架構(gòu)在這里就不進(jìn)行贅述,在分布式場(chǎng)景下,即使在 K8S 內(nèi),大多數(shù)用戶也會(huì)使用第三方注冊(cè)組件提供的服務(wù)發(fā)現(xiàn)能力。站在運(yùn)維成本、穩(wěn)定性、以及分層解耦等角度,除非一些特殊情況,很少會(huì)直接使用原生 Service 進(jìn)行服務(wù)發(fā)現(xiàn)和負(fù)載均衡,因此這些能力成為了微服務(wù)框架的標(biāo)配能力。
熟悉 Dubbo 的同學(xué)一定了解過,Dubbo 支持多種負(fù)載均衡算法,通過可擴(kuò)展機(jī)制集成到框架內(nèi)。Dubbo-go 亦是如此,針對(duì)多實(shí)例場(chǎng)景下,可以支持多種負(fù)載均衡算法, 例如 RR,隨機(jī)數(shù),柔性負(fù)載均衡等等。
下圖摘自 Dubbo 官網(wǎng)
Dubbo-go 的負(fù)載均衡組件
Dubbo-go 服務(wù)框架擁有一套接口級(jí)擴(kuò)展機(jī)制,可以根據(jù)配置,加載同一組件接口的不同的實(shí)現(xiàn)。其中就有隨機(jī)算法負(fù)載均衡策略,它是 Dubbo-go 默認(rèn)的負(fù)載均衡算法。在使用這種算法進(jìn)行負(fù)載均衡的情況下,所有 provider 都會(huì)根據(jù)一定的權(quán)重策略被隨機(jī)選擇。所有的provider 實(shí)例都有可能成為下游。
這種較為傳統(tǒng)的負(fù)載均衡算法會(huì)帶來隱患,即不會(huì)因?yàn)橹罢{(diào)用的結(jié)果,影響到后續(xù)調(diào)用過程中對(duì)下游實(shí)例的選擇。因此如果有部分下游實(shí)例處在上下線階段,造成短暫的服務(wù)不可用,所有隨機(jī)到該實(shí)例的請(qǐng)求均會(huì)報(bào)錯(cuò),在高流量的場(chǎng)景下,會(huì)造成巨大損失。
集群重試策略
下圖摘自Dubbo 官網(wǎng)
Dubbo-go 的集群重試策略是從 Dubbo 借鑒過來的,默認(rèn)使用 Failover(故障轉(zhuǎn)移) 邏輯,當(dāng)然也有failback,fallfast 等策略,也是依靠了組件可擴(kuò)展能力集成進(jìn)框架內(nèi)。
無論是上面提到的負(fù)載均衡,還是重試邏輯,都是基于“面向切面編程“的思路,構(gòu)造一個(gè)抽象化 invoker 的實(shí)現(xiàn),從而將流量層層向下游傳遞。對(duì)于 Failover 策略,會(huì)在負(fù)載均衡選擇下游實(shí)例的基礎(chǔ)上,增加對(duì)錯(cuò)誤請(qǐng)求的重試邏輯。一旦請(qǐng)求報(bào)錯(cuò),會(huì)選擇下一個(gè) invoker 進(jìn)行嘗試,直到請(qǐng)求成功,或超過最大請(qǐng)求次數(shù)為止。
集群重試策略只是增加了嘗試的次數(shù),降低了錯(cuò)誤率,但本質(zhì)上還是無狀態(tài)的,當(dāng)下游服務(wù)不可用時(shí),會(huì)造成災(zāi)難性的后果。
黑名單機(jī)制
黑名單機(jī)制是我去年實(shí)習(xí),師兄安排做的第一個(gè)需求,大致思路很簡(jiǎn)單,將請(qǐng)求拋錯(cuò)的 invoker 對(duì)應(yīng)實(shí)例的 ip 地址加入黑名單,后續(xù)不再將流量導(dǎo)入該實(shí)例,等過一段時(shí)間,嘗試請(qǐng)求它,如果成功就從黑名單中刪除。
這個(gè)機(jī)制實(shí)現(xiàn)邏輯非常簡(jiǎn)單,但本質(zhì)上是將無狀態(tài)負(fù)載均衡算法升級(jí)為了有狀態(tài)的。對(duì)于一個(gè)不可用的下游實(shí)例,一次請(qǐng)求會(huì)快速將該實(shí)例拉黑,其他請(qǐng)求就會(huì)識(shí)別出黑名單內(nèi)存在該實(shí)例,從而避免了其他的流量。
對(duì)于這種策略,在黑名單中保留的超時(shí)、嘗試從黑名單移除的策略等,這些變量都應(yīng)當(dāng)結(jié)合具體場(chǎng)景考慮,本質(zhì)上就是一個(gè)有狀態(tài)的故障轉(zhuǎn)移策略。普適性較強(qiáng)。
P2C 柔性負(fù)載均衡算法
柔性負(fù)載均衡算法是 Dubbo3 生態(tài)的一個(gè)重要特性,Dubbo-go 社區(qū)正在攜手 Dubbo 一同探索和實(shí)踐。一些讀者應(yīng)該在之前 Dubbo-go 3.0 發(fā)布的文章中看過相關(guān)介紹。簡(jiǎn)單來說,是一個(gè)有狀態(tài)的,不像黑名單那么“一刀切”的,考慮變量更廣泛、更全面的一種負(fù)載均衡策略,會(huì)在 P2C 算法的基礎(chǔ)之上,考慮各個(gè)下游實(shí)例的請(qǐng)求時(shí)延、機(jī)器資源性能等變量,通過一定策略來確定哪個(gè)下游實(shí)例最合適,而具體策略,將結(jié)合具體應(yīng)用場(chǎng)景,交由感興趣的社區(qū)成員來探索,目前是來自字節(jié)的牛學(xué)蔚(github@justxuewei) 在負(fù)責(zé)。
上述諸多負(fù)載均衡策略,都是站在客戶端的角度,盡最大能力讓請(qǐng)求訪問至在健康的實(shí)例上。在無損上下線角度來考慮,對(duì)于處于發(fā)布階段的不正常工作的實(shí)例,可以由客戶端通過合理的算法和策略,例如黑名單機(jī)制來過濾掉。
我認(rèn)為客戶端負(fù)載均衡是通用能力,對(duì)無損上下線場(chǎng)景的作用只是錦上添花,并不是的核心要素。究其本質(zhì),還是要從被“上下線”的服務(wù)端實(shí)例來考慮,從而解決根本問題。
2 服務(wù)端優(yōu)雅上線邏輯
相較于客戶端,服務(wù)端作為服務(wù)的提供者、用戶業(yè)務(wù)邏輯的實(shí)體,在我們討論的場(chǎng)景下邏輯較為復(fù)雜。在討論服務(wù)端之前,我們還是先重溫一下基礎(chǔ)的服務(wù)調(diào)用模型。
傳統(tǒng)服務(wù)調(diào)用模型
參考 Dubbo 官網(wǎng)給出的架構(gòu)圖,完成一次服務(wù)調(diào)用,一般需要三個(gè)組件:注冊(cè)中心,服務(wù)端,客戶端。
- 服務(wù)端首先需要暴露服務(wù),監(jiān)聽端口,從而具備接受請(qǐng)求的能力。
- 服務(wù)端將當(dāng)前服務(wù)信息例如ip和端口,注冊(cè)在中心化的注冊(cè)中心上,例如Nacos。
- 客戶端訪問注冊(cè)中心,獲取要調(diào)用的服務(wù)ip和端口,完成服務(wù)發(fā)現(xiàn)。
- 服務(wù)調(diào)用,客戶端針對(duì)對(duì)應(yīng) ip 和端口進(jìn)行請(qǐng)求。
這簡(jiǎn)單的四個(gè)步驟,就是 Dubbo-go 優(yōu)雅上下線策略的核心關(guān)注點(diǎn)。正常情況下,四個(gè)步驟依此執(zhí)行下來非常順利,邏輯也非常清晰。而放在一個(gè)大規(guī)模的生產(chǎn)集群內(nèi),在服務(wù)上下線時(shí)就會(huì)出現(xiàn)很多值得考量的細(xì)節(jié)。
我們要明白,上下線過程中的錯(cuò)誤是怎么產(chǎn)生的?我們只需要關(guān)注兩個(gè)錯(cuò)誤,就是:“一個(gè)請(qǐng)求被發(fā)送給了一個(gè)不健康的實(shí)例”,以及“正在處理請(qǐng)求的進(jìn)程被殺死”,上下線過程中幾乎所有的錯(cuò)誤都是來自于他們。
服務(wù)優(yōu)雅上線邏輯細(xì)節(jié)
服務(wù)上線時(shí),按照上述的步驟,首先要暴露服務(wù),監(jiān)聽端口。在保證服務(wù)提供者可以正常提供服務(wù)之后,再將自身信息注冊(cè)在注冊(cè)中心上,從而會(huì)有來自客戶端的流量發(fā)送至自己的ip。這個(gè)順序一定不能亂,否則將會(huì)出現(xiàn)服務(wù)沒有準(zhǔn)備好,就收到了請(qǐng)求的情況,造成錯(cuò)誤。
上面所說的只是簡(jiǎn)單的情況。在真實(shí)場(chǎng)景下,我們所說的一個(gè)服務(wù)端實(shí)例,往往包含一組相互依賴的客戶端和服務(wù)端。在 Dubbo 生態(tài)的配置中,被稱為 Service (服務(wù))和 Reference(引用) 。
舉一個(gè)業(yè)務(wù)同學(xué)非常熟悉的例子,在一個(gè)服務(wù)函數(shù)內(nèi),會(huì)執(zhí)行一些業(yè)務(wù)邏輯,并且針對(duì)多個(gè)下游服務(wù)發(fā)起調(diào)用,這些下游可能包含數(shù)據(jù)庫(kù)、緩存、或者其他服務(wù)提供者,執(zhí)行完畢后,返回獲得的結(jié)果。這對(duì)應(yīng)到 Dubbo 生態(tài)的概念中,其實(shí)現(xiàn)就是:Service 負(fù)責(zé)監(jiān)聽端口和接受請(qǐng)求,接受的請(qǐng)求會(huì)向上層轉(zhuǎn)發(fā)至應(yīng)用業(yè)務(wù)代碼,而開發(fā)者編寫的業(yè)務(wù)代碼會(huì)通過客戶端,也就是 Reference,請(qǐng)求下游對(duì)象。當(dāng)然這里的下游協(xié)議有多種,我們只考慮 dubbo 協(xié)議棧。
由上面提到這種常見的服務(wù)模型,我們可以認(rèn)為 Service 是 依賴 Reference 的,一個(gè) Service 的所有 Reference 必須都正常工作后,當(dāng)前 Service 才能正確接受來自上游的服務(wù)。這也就推導(dǎo)出了,Service 應(yīng)該在 Reference 之后加載,當(dāng)加載完成所有 Reference 后,保證這些客戶端都可用,再加載 Service,暴露能工作的服務(wù),最后再注冊(cè)到注冊(cè)中心,喊上游來調(diào)用。如果反過來,Service 準(zhǔn)備好了而 Reference 沒有,則會(huì)造成請(qǐng)求錯(cuò)誤。
因此,服務(wù)上線邏輯是 Consumer 加載 -> Provider 加載 -> Registry 服務(wù)注冊(cè)。
有讀者可能會(huì)疑惑,如果 Consumer 依賴當(dāng)前 實(shí)例自己的 Provider 怎么辦,Dubbo 的實(shí)現(xiàn)是可以不走網(wǎng)絡(luò)直接發(fā)起函數(shù)調(diào)用,Go 這邊也可以按照這種思路來處理,不過實(shí)現(xiàn)還待開發(fā)。這種情況相對(duì)較少,更多的還是上述大家熟悉的情況。
3 服務(wù)端優(yōu)雅下線邏輯
相比于服務(wù)上線,服務(wù)下線需要考慮的點(diǎn)更多一些。我們重新回到上一節(jié)提到的服務(wù)調(diào)用模型四步驟:
- 服務(wù)端首先需要暴露服務(wù),監(jiān)聽端口,從而具備接受請(qǐng)求的能力。
- 服務(wù)端將當(dāng)前服務(wù)信息例如ip和端口,注冊(cè)在中心化的注冊(cè)中心上,例如Nacos。
- 客戶端訪問注冊(cè)中心,獲取要調(diào)用的服務(wù)ip和端口,完成服務(wù)發(fā)現(xiàn)。
- 服務(wù)調(diào)用,客戶端針對(duì)對(duì)應(yīng) ip 和端口進(jìn)行請(qǐng)求。
如果一個(gè)服務(wù)將要下線,則一定要把相關(guān)的善后工作做好。現(xiàn)在的線上情況是這樣:客戶端正在源源不斷地給當(dāng)前實(shí)例請(qǐng)求,如果這個(gè)時(shí)候直接結(jié)束當(dāng)前進(jìn)程,一方面,將在一瞬間會(huì)有大量的 tcp 建立連接失敗,只能寄希望于第一章提到的客戶端負(fù)載均衡策略了;另一方面,有大量正在處理的請(qǐng)求被強(qiáng)制丟棄。這很不優(yōu)雅!所以當(dāng)實(shí)例知道自己要被終止后,首先要做的就是告訴客戶端:“我這個(gè)服務(wù)要被終止了,快把流量切走”。這體現(xiàn)在實(shí)現(xiàn)中,就是把自身的服務(wù)信息從注冊(cè)中心刪除。客戶端拿不到當(dāng)前實(shí)例IP后,不會(huì)再將請(qǐng)求發(fā)過來,這個(gè)時(shí)候再終止進(jìn)程才優(yōu)雅。
上面所說的,也只是簡(jiǎn)單的情況。在真實(shí)場(chǎng)景之下,客戶端可能并沒有那么快地把流量切走,并且當(dāng)前服務(wù)手里還有一大批正在處理的任務(wù),如果貿(mào)然終止進(jìn)程,可以形象地理解成將端在手里的一盆水撒了一地。
有了這些鋪墊,我們來詳細(xì)地聊一聊服務(wù)下線的步驟。
優(yōu)雅下線的使用和觸發(fā)
上面的小故事里面提到,進(jìn)程首先要知道自己“要被終止”了,從而觸發(fā)優(yōu)雅下線邏輯。這個(gè)消息可以是信號(hào)量,當(dāng) k8s 要終止容器進(jìn)程,會(huì)由 kubelet 向進(jìn)程發(fā)送 SIGTERM 信號(hào)量。在 Dubbo-go 框架內(nèi)預(yù)置了一系列終止信號(hào)量的監(jiān)聽邏輯,從而在收到終止信號(hào)后,依然能由進(jìn)程自己來控制自己的行動(dòng),也就是執(zhí)行優(yōu)雅下線邏輯。
不過有些應(yīng)用會(huì)自己監(jiān)聽 SIGTERM 信號(hào)處理下線邏輯。比如,關(guān)閉 db 連接、清理緩存等,尤其是充當(dāng)接入層的網(wǎng)關(guān)類型應(yīng)用,web 容器和 RPC 容器同時(shí)存在。這個(gè)時(shí)候先關(guān)閉 web 容器還是先關(guān)閉 RPC 容器就顯得尤其最重要。所以 Dubbo-go 允許用戶通過配置internal.signal來控制 signal信號(hào)監(jiān)聽的時(shí)機(jī),并通過 graceful_shutdown.BeforeShutdown()在合適的時(shí)機(jī)優(yōu)雅關(guān)閉 rpc 容器。同樣,Dubbo-go 也允許用戶在配置中選擇是否啟用新號(hào)監(jiān)聽。
反注冊(cè)
上面提到,服務(wù)端需要告訴客戶端自己要終止了,這個(gè)過程就是通過注冊(cè)中心進(jìn)行反注冊(cè)(Unregister)。常見的服務(wù)注冊(cè)中間件,例如 Nacos 、Zookeeper、Polaris 等都會(huì)支持服務(wù)反注冊(cè),并將刪除動(dòng)作以事件的形式通知給上游客戶端。客戶端一定是隨時(shí)保持對(duì)注冊(cè)中心的監(jiān)聽的,能否成功請(qǐng)求與否,很大程度取決于來自注冊(cè)中心的消息有沒有被客戶端及時(shí)監(jiān)聽和作出響應(yīng)。
在 Dubbo-go 的實(shí)現(xiàn)中,客戶端會(huì)第一時(shí)間拿到刪除事件,將該實(shí)例對(duì)應(yīng) invoker 從緩存中刪除。從而保證后續(xù)的請(qǐng)求不會(huì)再流向該 invoker 對(duì)應(yīng)的下游。
反注冊(cè)過程雖然很快,但畢竟是跨越三個(gè)組件之間的事情,無法保證瞬間完成。因此便有了下一步:等待客戶端更新。
和后面步驟有些關(guān)聯(lián)的是,在當(dāng)前階段只進(jìn)行反注冊(cè),而不能進(jìn)行反訂閱,因?yàn)樵趦?yōu)雅下線執(zhí)行的過程中,還會(huì)有來自自身客戶端向下游的請(qǐng)求,如果反訂閱,將會(huì)無法接收到下游的更新信息,可能導(dǎo)致錯(cuò)誤。
等待客戶端更新
服務(wù)端在優(yōu)雅下線邏輯的反注冊(cè)執(zhí)行后,不能快速殺死當(dāng)前服務(wù),而會(huì)阻塞當(dāng)前優(yōu)雅下線邏輯一小段時(shí)間,這段時(shí)間由開發(fā)人員配置,默認(rèn)3s,應(yīng)該大于從反注冊(cè)到客戶端刪除緩存的時(shí)間。
經(jīng)過了這段等待更新的時(shí)間,服務(wù)端就可以認(rèn)為,客戶端已經(jīng)沒有新的請(qǐng)求發(fā)送過來了,便可以亮起紅燈,邏輯是拒絕一切新的請(qǐng)求。
等待來自上游的請(qǐng)求完成
這里還是不能殺死當(dāng)前進(jìn)程,這就像自己的手里還端著那盆水,之前做的只是離開了注水的水龍頭,但并沒有把盆里的水倒干凈。因此要做的還是等待,等待當(dāng)前實(shí)例正在處理的,所有來自上游的請(qǐng)求都完成。
服務(wù)端會(huì)在一層 filter 維護(hù)一個(gè)并發(fā)安全的計(jì)數(shù)器,記錄所有進(jìn)入當(dāng)前實(shí)例但未返回的請(qǐng)求數(shù)目。優(yōu)雅下線邏輯會(huì)在這時(shí)輪詢計(jì)數(shù)器,一旦計(jì)數(shù)器歸零,視為再也沒有來自上游的請(qǐng)求了,手里端著的來自上游的水也就倒干凈了。
等待自己發(fā)出的請(qǐng)求得到響應(yīng)
走到這一步,整條鏈路中,自己上游的請(qǐng)求都移除干凈了。但自己往下游發(fā)出的請(qǐng)求還是個(gè)未知數(shù),此時(shí)此刻也許有大量由當(dāng)前實(shí)例發(fā)出,但未得到響應(yīng)的請(qǐng)求。如果這時(shí)貿(mào)然終止當(dāng)前進(jìn)程,會(huì)造成不可預(yù)知的問題。
因此還是類似于上述的邏輯,服務(wù)在客戶端 filter 維護(hù)一個(gè)線程安全的計(jì)數(shù)器,由優(yōu)雅下線邏輯來輪詢,等待所有請(qǐng)求都已經(jīng)返回,計(jì)數(shù)器歸零,方可完成這一階段的等待。
如果當(dāng)前實(shí)例存在一個(gè)客戶端,源源不斷地主動(dòng)向下游發(fā)起請(qǐng)求,計(jì)數(shù)器可能一直不歸零,那就要依靠這一階段的超時(shí)配置,來強(qiáng)行結(jié)束這一階段了。
銷毀協(xié)議,釋放端口
這時(shí),就可以放心大膽地做最后的工作了,銷毀協(xié)議、關(guān)閉監(jiān)聽,釋放端口,反訂閱注冊(cè)中心。用戶可能希望在下線邏輯徹底結(jié)束后,端口釋放后,執(zhí)行一些自己的邏輯,所以可以提供給開發(fā)者一個(gè)回調(diào)接口。
三 優(yōu)雅上下線的效果
按照上述的介紹,我們?cè)诩簝?nèi)進(jìn)行了壓測(cè)實(shí)驗(yàn)和模擬上下線實(shí)驗(yàn)。
使用一個(gè) client 實(shí)例,5個(gè) proxy 實(shí)例,5個(gè) provider 實(shí)例,請(qǐng)求鏈路為:
client -> proxy -> provider
因?yàn)橘Y源問題,我們選擇讓客戶端保證 5000 tps 的壓力,通過 dubbo-go 的 prometheus 可視化接口暴露出成功率和錯(cuò)誤請(qǐng)求計(jì)數(shù),之后針對(duì)鏈路中游的 proxy 實(shí)例和鏈路下游的 provider 實(shí)例進(jìn)行滾動(dòng)發(fā)布、擴(kuò)容、縮容、實(shí)例刪除等一系列實(shí)驗(yàn),模擬生產(chǎn)發(fā)布過程。
期間我記錄了很多數(shù)據(jù),可以把一個(gè)比較明顯的對(duì)比展示出來。
不使用優(yōu)雅上下線邏輯:更新時(shí)成功率大幅降低,錯(cuò)誤數(shù)目持續(xù)升高,客戶端被迫重啟。
優(yōu)雅上下線優(yōu)化后:無錯(cuò)誤請(qǐng)求,成功率保持在100%
四 Dubbo-go 在服務(wù)治理能力的展望
Dubbo-go v3.0 從去年年底正式發(fā)版,到現(xiàn)在過了一個(gè)多月左右的時(shí)間,3.0 發(fā)布對(duì)我們而言不是大功告成,而是踏上了展望未來的一個(gè)新階梯。我們即將發(fā)布 3.1 版本,這一版本將擁有優(yōu)雅上下線能力。
在 3.0 籌備階段,我有想過如果一款服務(wù)框架從傳統(tǒng)設(shè)計(jì)走向未來,需要一步一步走下來,需要有多個(gè)必經(jīng)之路:從最基本的用戶友好性支持、配置重構(gòu)、易用性、集成測(cè)試、文檔建設(shè);到實(shí)現(xiàn)傳輸協(xié)議(Dubbo3) Triple-go 的跨生態(tài)、穩(wěn)定、高性能、可擴(kuò)展、生產(chǎn)可用;再到我們 3.0 發(fā)版之后的 服務(wù)治理能力、運(yùn)維能力、可視化能力、穩(wěn)定性,其中就包括了優(yōu)雅上下線、流量治理、proxyless;再到形成生態(tài),跨生態(tài)集成。這樣走,才能一步一個(gè)腳印,不斷積累,不斷迭代。
運(yùn)維能力和服務(wù)治理的充實(shí)和優(yōu)化,將作為后續(xù)版本的重要 Feature ,我們將會(huì)進(jìn)一步完善流量治理、路由、Proxyless Service Mesh、還有文中提到的柔性負(fù)載均衡算法等方面,這些都是今年社區(qū)工作的重點(diǎn)。
Dubbo-go 生態(tài),同開發(fā)者同在!
[1] https://github.com/apache/dubbo-go/issues/1685