OpenSergo & Dubbo 微服務治理最佳實踐

01 Why 微服務治理?

現代的微服務架構裏,我們通過將系統分解成一系列的服務並通過遠程過程調用聯接在一起,在帶來一些優勢的同時也爲我們帶來了一些挑戰。

如上圖所示,可以看到詞雲中所展示的都是目前微服務架構在生產上所遇到的挑戰。比如,最常見的流量激增的場景,近一年內 AIGC 突然爆火,相關網站/服務都存在過因爲激增流量導致服務不可用的情況,可能會讓我們錯過一個最佳的增長窗口。

再比如缺乏容錯機制,某視頻網站的某個服務異常,隨調用鏈擴散,導致全站入口不可用,影響千萬用戶,產生實質性的經濟損失。這些生產故障頻頻發生,也是在提醒我們穩定性是用好微服務的重大挑戰之一。

爲了保障微服務的穩定性,我們就需要做一些架構的演進。

我們先看一下左側的微服務 3 大件,這個大家已經很熟悉了,通過這三者的配合,我們的應用就能夠正常使用了,但是距離生產可用其實還有很大一段距離,各個企業和社區爲了消除這其中的距離都有一些探索和實踐,比如 Dubbo 社區在 Dubbo3 中引入一系列諸如流量管理、高可用性的能力來保障微服務的穩定性,這些措施可以統稱爲微服務治理。

所以其實可以看出大家已經意識到,從把微服務跑起來到真的生產可用,微服務治理是必不可少的一環。但微服務治理要做些什麼,如何去做其實都還比較模糊。

從軟件生命週期的角度,我們可以把微服務治理分成三個域,開發態與測試態、變更態、運行態。

在這三個域中都面臨着很多挑戰,對於這些挑戰大家也有着一些探索和實踐,比如對於發佈有損的問題,我們可以通過無損上下線來解決,變更的影響面通過灰度來控制,對於不確定流量使用流控、熱點防護,不穩定調用使用熔斷與隔離。

可以看到在各個域中都有一些成熟的方案和效果很好的實踐。但是不管是阿里還是其他公司,在體系化落地微服務治理時都會遇到很多問題。

02 OpenSergo:服務治理控制面與標準規範

首先我們涉及的組件有很多,在微服務架構中,我們會需要有 Dubbo 這樣的調用框架,Nacos 這樣註冊中心,Sentinel、Hystrix 這樣的穩定性中間件等等,這些組件沒辦法進行統一治理,管控成本就會變得非常高。

其次是概念不統一,比如在 Envoy 中的隔離與 Sentinel 中的隔離完全不是一個意思,Envoy 的隔離是摘除不健康實例,Sentinel 的隔離是併發控制,這就會使開發者理解成本很高。

同時各個企業社區都有自己的最佳實踐,這也就導致大家能力上是不對齊的,沒有統一的標準。

還有配置不統一的問題相信大家都很有體感,比如 Sentinel、Hystrix、Istio 都有熔斷的能力,但是配置卻各有差別,需要開發者分別學習,還要注意不混淆,不利於理解,也不利於統一管控。

可以發現由於這些問題,我們在落地體系化微服務治理時會有很大的阻力,我們需要的是一個統一的治理界面來讓我們更好地做微服務治理,因此我們提出了 OpenSergo 這個項目。

而 OpenSergo 期望提出一套開放通用的、面向雲原生架構的微服務治理解決方案及標準規範,來助力保障微服務高可用,上圖的四個部分就是 OpenSergo 社區的願景。

OpenSergo 社區會基於業界微服務治理場景與實踐抽象成規範,通過這種方式去解決前面提到的概念、配置、能力不統一的問題,並用統一的管控面去承載,降低使用和維護成本。

同時在縱向上,我們針對鏈路上的每一環進行抽象,覆蓋完整的場景,在橫向上,無論是 Java 生態,Go 生態或是其他語言,無論是傳統微服務還是 Mesh 架構,都會納入到這套統一的體系中。

但是 OpenSergo 作爲一個開放標準,僅憑藉阿里是不夠的,所以我們聯合了多家公司以及社區比如 bilibili、中國移動等,共同建設這套開放標準,希望能夠真正解決微服務穩定性的風險。

接下來簡單介紹一下 OpenSergo 的架構體系,前面也介紹了 OpenSergo 社區會基於場景抽象出 OpenSergo 的 Spec,但這只是第一步,爲了承載這些標準規範我們就需要一個控制面,社區在一開始的演進中選擇從 0 開始開發一個控制面來做治理規則的管控、監聽與下發。

但是隨着社區的演進,我們發現基於 Istio 去擴展,成本更低,也能夠複用更多的能力,因此在後續的演進中我們會選擇結合 Istio 擴展控制面與決策中心實現治理規則統一管控、治理策略預計算。

在有了控制面後我們還需要數據面來進行具體治理能力的實現,它可以是像 Sentinel 這樣的中間件,也可以是框架本身。控制面與數據面之間的通訊在初始的架構中是基於 gRPC 構建的鏈路,但在確定了後續演進方向會基於 Istio 擴展後,社區選擇擁抱 XDS,儘可能服務它的鏈路,對於一些無法承載的我們再使用自身的 gRPC 鏈路。

前面也提到社區控制面的後續演進是基於 Istio 擴展的,Istio 本身也有一些流量治理能力,並有着一定的普及度。但是 Istio 主要關注流量管理,讓流量到達該去的地方而不是微服務治理,所以在微服務穩定性的場景下,Istio 所提供的這些能力是不足以滿足我們的需求的。

因此我們在 Istio 的基礎上,基於微服務穩定性的一些場景,比如前面提到的變更態穩定性、運行時穩定性去抽象、制定了滿足需求的規範標準,希望能夠更加貼合微服務場景。所以整體上我們在微服務治理領域會是 Istio 的超集,而不是互斥關係。

接下來我們一起看一下 OpenSergo 的標準規範是如何解決前面所提到的這些場景。

首先我們聊一下流量路由,它的主要作用是將符合一定特徵的流量路由到指定的 workload 上,一般大家會用這種能力來實現灰度、同 AZ 路由等方案。

基於 Istio VirtualService/DestinationRule 的格式社區定義了流量路由 spec,但我們在調研以及實踐的過程中發現,它並不能很好的滿足微服務場景下的需求。所以爲了更貼近微服務的場景去做了擴展。比如我們增加了路由失敗後的處理邏輯,這在微服務架構中是很常見的需求。

又由於 Istio 主要關注的是 HTTP 請求,它的 CRD 不能夠很好地承載像 Dubbo 這樣的 RPC 調用,所以我們爲此增加了更多 RPC 模型的支持。後續我們也會探索與社區標準結合的方案,使我們的 Spec 更加通用與標準。

前面所提到的灰度,在阿里集團內部數年的安全生產實踐中,與可監控、可回滾一起被定義爲安全變更的三板斧,其中灰度是控制變更影響面,保障變更穩定性的必不可少的能力。

爲了實現灰度,我們通常有幾種方案,第一種是物理隔離,我們通過部署兩套一樣的環境來實現灰度,但是這種方案的部署和維護成本都很高。

爲了提高資源利用率,便產生了第二種方案,流量灰度。我們不部署獨立的環境,而是在流量的每一跳進行流量的特徵匹配,並且由此決定去往灰度實例還是 base 實例,這種方案相較與前者更加靈活高效,可以通過前面提到的流量路由能力來實現。但是需要我們在每一跳都配置路由規則,相對比較繁瑣。

並且由於有些信息在後續鏈路是獲取不到的,比如 uid,導致這個方案的實施有一定的困難。於是便產生了第三種方案,全鏈路灰度,我們通過在流量入口處進行流量匹配並打上標籤,標籤會自動沿着調用鏈路透傳,後續鏈路根據標籤來進行路由。通過這種方式,我們就能夠更簡潔地去定義灰度。Opensergo 針對這種場景抽象了對應的 CRD。

我們將這個 CRD 稱之爲 TrafficLane 也就是泳道,我覺得還是比較形象的,大家看一下上邊的圖片,橙色的是正常的流量走向,灰色的是灰度流量的走向,就像是將一個池子分成了多個泳道。

泳道的 CRD 由三個部分組成,也比較好理解,首先我們需要去匹配灰度流量,所以就要去定義匹配的條件,然後定義爲這些流量打上什麼標籤,最後再定義這個標籤以什麼方式去透傳。

通過這樣的 CRD 我們就定義了一條灰度泳道。但是如果只是定義是不足以實現全路灰度的,我們還需要藉助 OpenSergo 體系全鏈路全方位框架的一個支持,才能讓標籤在這些框架中自動的透傳,這些框架也能通過標籤進行路由。其中流量染色和標籤透傳會藉助標準的 Trcae 體系去實現,比如 OpenTelemetry。

上圖右側是一個 CRD 的例子,大家可以簡單看一下。

接下來我們一起看一下運行態穩定性的場景。

我們主要提兩個場景,第一個是流量激增的場景,比如雙十一的秒殺活動,一開始流量是穩定的情況下,系統也處於穩態。但是當流量激增的時候,系統就會開始往不穩定的方向發展,異常調用也會激增,最後就會變成不可用的狀態。對於這類場景,我們可以用流量控制的能力拒絕超出容量的請求,或是通過流量平滑的能力削峯填谷,讓流量處於比較平穩的狀態,避免服務的不可用。

第二個是不穩定調用導致服務不可用的場景,比如我們調用一些第三方服務經常會出現不穩定的情況,這裏的不穩定主要指異常或是慢調用。以 Dubbo 爲例,當服務提供方出現慢調用的時候,會導致服務消費方的線程堆積,影響到其他的正常調用甚至是整個服務的穩定性,並且這種風險會沿着調用鏈反向傳遞、擴散最終影響整個系統的穩定性。這時我們可以通過併發控制或是熔斷保護來限制慢調用對資源的佔用,保障系統的整體穩定性。

針對前面提到的這些場景,OpenSergo 也制定了相關的 CRD。在業界的實踐中 Sentinel 是一個成熟的流量防護方案,在阿里內部積累了大量的流量防護相關的場景和實踐,2018 年開源以後在業界進一步豐富了這些積累,我們從這些積累中抽象出了一套流量防護的規範標準。

那麼一條流量防護的規則應該包含哪些內容,大家可以簡單想一下。

首先我們要確定的是要針對怎樣的流量,我們可以按接口去劃分,也可以按請求中的特徵去劃分。確定了目標之後,我們就需要定義要採取怎樣的治理策略。這裏的策略包括了剛纔提到的這些策略,以及更高階的比如自身過載保護等策略。

最後由於限流本身是有損的,但是我們不希望這種有損傳遞到用戶側,因此我們需要爲不同的規則配置不同行爲,從而使得在用戶側的表現是比較友好的,比如最基本的對於搶購場景的限流,我們可以返回一個排隊中,請稍後的提示。

上圖右側是一個 CRD 的示例,流量目標爲接口名爲 /foo 的請求,策略爲閾值爲 10 的全侷限流,fallback 爲特定的返回體。

通過這樣的 CRD 配置,不管是 Dubbo 框架還是其他框架,我們都能很方便的使用流量防護的能力。

03 OpenSergo&Dubbo 最佳實踐

對於框架開發者來說想要接入到 OpenSergo 的體系中其實有兩種方式:

一種是通過對接 OpenSergo 體系的數據面來接入,框架開發者只需要實現對接 Sentinel 的適配模塊就可以完成對接工作。而對於有特殊要求或是更貼近特定場景的框架,也可以自行對接 OpenSergo 的標準,來接入 OpenSergo 體系。

對於用戶來說,不管是哪一種方式,都只需要簡單地引入一些依賴,就可以無感地獲取 OpenSergo 定義的微服務治理能力,並能在統一的控制面管控這些框架的微服務治理能力,大大提高使用微服務治理的體驗與效率。講完了接入的方式,我們再一起來看下實現的效果。

第一個實踐是全鏈路灰度控制消除變更態穩定性風險。這是一個簡單的 demo,我們只需要部署這樣的一個CRD,定義 /A/dubbo 的請求,當它的參數裏出現 name=xiaoming 的時候,我們就把它導向灰度的環境,對於不符合要求的流量,就還是走基線環境,可以看到現在的請求走向是符合我們預期的。

但我們的生產環境會比 demo 複雜的多,會涉及各種框架,比如 RokcetMQ、spring cloud alibabab。但只要這些框架對接了 Opensergo 的體系,就可以用這一個 CRD 來做到全鏈路,全框架的灰度。

第二個實踐是流量防護與容錯保障運行時穩定性——不穩定調用場景。這裏使用一個簡單的 Demo,應用 A 通過 Dubbo 調用應用 B。右側是一個正常接口和慢調用接口的流量圖,紫色的是總流量,黃色的是拒絕流量,橙色的異常流量。在一開始慢調用還沒有發生,系統處於穩態,沒有異常流量。

在第一個時間點,我手動調整了慢調用接口的 RT,慢調用發生,異常流量出現,同時由於慢調用大量地佔用了 Dubbo 的線程資源,導致正常調用的資源受到擠佔,同樣出現大量的異常流量,Dubbo 側也出現了線程池耗盡的異常。

大家可以想一下,這種場景下我們應該配置什麼規則來解決這個問題,其實這個時候很多人會想要流量控制來做限流希望能解決這個問題,我們一起看下它的一個效果。

在第二個時間我配置了一條限流規則,可以看到情況雖然有所緩解,但是依舊有大量報錯,這是因爲在慢調用場景下,請求已經出現堆積,僅僅通過 QPS 限流還是會導致請求湧入進一步堆積。

所以我們真正需要的是併發控制,在第三個時間點我配置併發控制規則來限制慢調用接口的併發數,也就是正在處理的請求數。可以看到通過這種限制,即便慢調用仍然存在,但是它所能佔用的線程資源被限制,正常接口得以正常調用,從而避免穩定性風險的擴展,保障應用的穩定性。

第三個實踐是流量防護與容錯保障運行時穩定性——自適應過載保護。可以看到我們的 demo 在持續的高負載下,異常流量開始逐漸上升,系統的穩態被破壞,這時我們可以通過配置自適應過載保護規則,來自適應地調節限流行爲,達到消除異常請求,幫助系統重新回到穩態的效果。

目前的策略我們在開源已經支持了 BBR,在內部的實踐中我們也有用 PID。這些策略我就不在這裏詳細介紹了,大家感興趣可以去我們的開源社區一起參與討論。

從這三個例子可以看到 Dubbo 通過對接 Sentinel 接入 OpenSergo 體系後就無感地具備了 OpenSergo 所定義的通用的治理能力,並且能夠通過統一的控制平面來管控。

而對於其他框架也是一樣,可以設想一下如果我們生產上所涉及的所有框架都對接了 OpenSergo 體系,那我們就可以在一個控制面上管控所有服務,所有框架的微服務治理能力,更好地保障系統的穩定性。

04 OpenSergo 的未來之路

這是多語言服務治理的生態大圖。在生態上,我們希望 OpenSergo 是全鏈路多語言異構化的,我們會主要關注 Java/Go + Gateway + Mesh 生態,在生態上不斷去覆蓋更多的框架。

在能力上我們會不斷抽象並落地更多的通用的微服務治理能力。包括流量防護、自愈、服務容錯、服務鑑權等等。

目前我們已經和很多社區建立了聯繫和合作,比如 Dubbo、ShenYu、APISIX、Higress、RocketMQ、MOSN 等等,其中也有不少已經有了一些實質性的進展。

接下來分享一下我們近期的規劃。

  • 控制面方面,我們會逐步推動控制面的生產可用,在明年 3 月份發佈 GA 版本,讓大家能夠在生產上去驗證微服務治理體系。
  • Spec 方面,我們會去支持微服務安全治理、離羣實例摘除,並持續地與社區標準集成。
  • 治理能力的演進上,我們會重點完成 Sentinel 2.0 流量治理的升級,並在安全和自適應方向上進行探索。
  • 在社區合作上,我們會繼續推進與社區間的交流與合作,推進各個微服務治理領域的生態落地,統一控制面、Spec 共建。

雖然阿里在集團以及雲上積累了大量的經驗和場景,但穩定性的問題是複雜的,場景是多樣的,僅憑一方不足以覆蓋所有穩定性的場景,也不足以成爲標準,所以微服務治理技術、生態與標準化的演進還需要各個企業和社區的共同參與。大家可以從以下三個方面入手來參與社區。

  • 微服務治理的 spec,各個社區和企業都是各自領域中引領者,大家能從各自的場景和最佳實踐出發,一起制定與完善標準規範。
  • 微服務統一控制面的演進,這一塊其實有很多的可能性,作爲控制面其實它處在一個決策者的位置,一定程度上具備整個系統的上帝視角,在 AI 技術火爆的當下大有可爲。
  • 治理能力與社區生態的貢獻,大家可以參與到服務治理能力的演進中,也可以貢獻各個社區和 OpenSergo 體系的對接。

最後我想說,微服務治理其實是一個很廣闊的平臺,參與其中,你可以接觸到各個領域的技術與場景,而不是被限制在單點技術範圍內摸爬滾打。歡迎企業與社區同學加入開源貢獻小組,一起主導下一代微服務技術體系的演進!

作者:何家歡,阿里雲 MSE 研發工程師

點擊立即免費試用雲產品 開啓雲上實踐之旅!

原文鏈接

本文爲阿里雲原創內容,未經允許不得轉載。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章