“
Service Mesh 是近兩年比較火的微服務化新方式,也產生了一大批以 Istio 為代表的 Service Mesh 實現。
微博基于實際業務需求,打造并開源了自己的 Weibo Mesh,并且內部已經在重點業務上進行大規模落地。
本文將從如下幾個部分為大家詳細解讀 Weibo Mesh,希望可以為大家帶來服務化方向上的一些靈感,更好的服務于自己的業務:
微博服務化挑戰
服務化新思路
Weibo Mesh 方案介紹
生產實踐
總結
微博服務化挑戰
首先,為大家介紹下微博服務化面臨的挑戰。微博的形態比較特殊,除去常態午/晚高峰流量較高外,突發熱點事件的殺傷力更大。
熱點事件來襲時,流量極短時間內呈現爆炸式增長,并且往往事件爆發沒有任何征兆。這對于微博服務化及穩定性均帶來了極大挑戰。
如果其中某一個環節掉鏈子,不能及時感知并作出應對,極有可能會導致雪崩式宕機,導致全站掛掉。
那么怎么解決這種問題呢?首先會想到自動擴縮容/降級建設,但是我們決策依賴是什么呢?又如何滿足系統可觀測性要求,以及如何評價系統可用性及冗余度呢?
究其本質,系統的服務治理建設非常重要,它會直接影響到服務可用性。但是微博技術棧的多樣性又導致了在微服務化和服務治理方面困難重重。
從技術層面看,微博的典型服務調用大致如上圖,業務體系會調用平臺體系的多個接口,例如通過平臺接口獲取微博內容。
平臺體系主要是 Java 技術棧,本來微服務相關解決方案也多,再加上服務化時間較早,平臺微服務體系建設相對比較完善,同時也產出了一些優秀開源框架,比如 Motan 微服務框架。
業務方的語言棧:多樣化,基本涵蓋了所有主流語言,其中 PHP 相關系統流量占比較大。
調用鏈路:通常情況下業務方和平臺使用 RestFul API 進行交互。一次請求調用要經過 4,7 層的層層調度,服務穩定性還時常遭受網絡抖動及 DNS 不穩定的困擾,在中間層的消耗是不容忽視的。
另外,業務部門的語言種類繁多,間接導致了各部門微服務體系建設參差不齊。
峰值流量應對需要所有部門所有業務模塊的通力協助和聯動,考驗的是整站實力,我們需要所有模塊都能具備高水平的服務治理能力。因此我們迫切需要解決跨語言微服務化問題。
上圖是微博平臺內部的微服務體系支撐圖,平臺實現以 Motan 框架為核心的微服務治理體系 。
此外,還有自研的 Vintage 注冊中心及 Open DCP 智能彈性調度平臺以及 Graphite 實時監控平臺,可以看出平臺微服務架構有完善的 DevOps 支撐。
業界的大趨勢是云原生,微服務作為云原生重要的一環,是我們必須要突破的。
微博服務化新思路
跨語言服務治理嘗試
為了解決跨語言服務治理的問題,我簡單介紹一下我們嘗試過哪些解決方案。
這里有個大背景,Motan 由于是微博內部使用已久,經歷過重大考驗并且開源的優秀框架,它積累了很多優秀的服務治理經驗,所以我們服務化改造要充分考慮 Motan 的存在。
我們嘗試將 Motan 適配 Yar 這種 PHP 的 RPC 協議,PHP 可以與 Server 端的 Java 進行通訊,但 PHP 并不能進行服務發現。
于是我們在 PHP 旁邊加一個 Daemon 程序,也考慮過使用 Nginx,來做服務發現。
當然問題也是顯而易見的,這樣改造會導致業務侵入變高,成本變大,擴展性也較差,何況并沒有解決 PHP 做 Server 端的服務治理問題。
我們也嘗試過 GRPC,當然跨語言調用能解決,但是這里遇到幾個問題,一個是如何進行服務治理,另外一個是 PB 序列化問題。
由于微博場景的內容結構體非常大,效率并不比 Json 高,業務變更導致 PB 文件的變更讓升級維護成本變得難以接受,另外序列化數據遇到問題調試也變的困難。
此外 ,技術棧的多樣性也會引發一系列的問題。即使我們解決了 PHP 到 Java 的調用問題。但是相同的治理功能,不同的語言不可能再實現一遍。
Motan 框架積累下來的服務治理經驗是我們需要傳承和發揚的,那如何均衡這些問題及解決方案呢?
跨語言服務化本質
我認為跨語言服務化的本質,總結下來有兩點:
數據交互
服務治理
數據交互設計要考慮跨語言及協議中立,服務治理設計要靈活全面且可擴展。
上圖我列舉了跨語言服務化方式的優缺點:
傳統的 HTTP 代理,可以解決不同服務之間的調用。HTTP 就是傳統的走網關,較容易實現,但因為內部的調用每個人都要加網關,這就增加了鏈路,導致擴展能力低。
RPC 模塊或者 Agent 代理。RPC 框架業界有很多,大多 Java 棧的,功能也齊全,但跨語言維護成本非常之高。
Agent 代理是一個新的思路,Agent 代理的研發成本、維護成本、使用成本對比起來均比較折中,即我們獨立一個 Agent 來專門解決我們遇到的跨語言服務化困擾。
那樣既能釋放傳統的業務端的服務治理壓力,又能傳承 Motan 框架的精髓,也不需要實現多語言服務治理邏輯,更可以讓業務和 Agent 互相獨立發展,可謂一舉多得。
這個思路最終也演化成了今天的 Weibo Mesh:
由此微博走向了 Service Mesh。微博走向 Service Mesh,并不是盲目追趕最新的技術潮流。
我們立足于現狀,立足于解決實際業務問題,并一步步探索過后,發現最終的解決方案與 Service Mesh 思路不謀而合。從側面也驗證了 Service Mesh 思路解決服務化問題的合理性和前瞻性。
上圖,我們可以用正交分解法來理解 Service Mesh,可以看到,原有的微服務被拆分成業務邏輯層和服務交互治理層,其中服務交互治理層抽象為 Service Mesh。
Service Mesh 把服務間的交互與治理邏輯從業務中進行解耦,抽象獨立成一個專門的處理模塊。
通常 Mesh Agent 以 Sidecar 的形式和業務進行本機部署,Agent(以下 Mesh Agent 簡稱 Mesh 或 Agent)可以理解為服務的基礎設施層,業務無需關心服務間交互/治理細節,全部交由 Agent 統一處理。
Service Mesh 帶來的是微服務架構思路的轉變,為業務開發帶來了諸多架構上的優勢,Agent 及業務均可獨立發展,通常 Agent 交由運維管理,業務開發交由業務線,故整體可以做到持續開發、持續集成。
Mesh 思路不光可以解決跨語言服務化的問題,也可以解決資源服務化問題,而這些改造基本都對業務方透明。
Weibo Mesh 方案介紹
下面具體介紹下 Weibo Mesh 的實現方案。上圖是 Weibo Mesh 架構圖,除了必須的 Mesh Agent 外,考慮到業務遷移及實際落地需要,這里在業務代碼和 Mesh 之間增加了 Client。
這個 Client 非常輕,其核心功能是封裝 Mesh 請求,方便業務進行 Mesh 調用,最大限度降低業務遷移成本。
實際上在 Client 中我們也實現了其他一些對業務友好的功能,同時對 Mesh 調用進行了功能增強。
比如可以在 Client 中進行跨語言的序列化,Mesh 故障轉移,請求多發,超時控制等。
當然不同業務方可以進行功能定制。Client 和業務相同的語言編寫,其核心目的是幫助業務進行平滑遷移。
Mesh 層實現了 Service Mesh 的核心功能,包括發現、交互、路由、治理。
Weibo Mesh 是由 Go 實現的,國內各大廠商的 Mesh 數據平面也大多使用 Go 來實現。
Go 具有優秀的性能及易用性,又是云時代比較推崇的語言,未來 Mesh 層極有可能結合容器,沉淀成為容器的一個基礎設施層。
Weibo Mesh 數據面
剖析一個 Service Mesh 服務,一般通過數據面和控制面。首先來看一下 Weibo Mesh 在數據平面的表現,包含五個核心模塊:
Cluster(集群管理),對分組下通過服務發現回來的的節點列表的抽象管理。
HA(高可用策略)、LB(負載均衡)。
Endpoint(服務節點的抽象),本質上是 IP 和端口,但從代碼層面看,它是服務節點的抽象,通過 Endpoint 可以進行直接的調用,可以理解為它是調用的一個單元。
Protocol(Motan2/傳輸協議+Simple/序列化協議)。
下面一一介紹這些模塊。
①Cluster 模塊
調用方請求通過本機的 Mesh,在 Cluster 模塊處理中,首先經過一系列集群粒度的 Filter Chain(過濾鏈,包含集群 Metric,熔斷,攔截,鑒權,分組切換等功能,它們以鏈式結構進行組織調用,支持任意過濾功能擴展)。
然后再經過高可用策略跟負載均衡策略篩選出一個可用的 Endpoint,在 Endpoint 中又會進行請求粒度的 Filter Chain(單機的日志記錄,Metric 等),通過進行請求序列化,根據傳輸協議進行組裝,最終通過 Endpoint 把請求發到對端的 Mesh 上。
②高可用策略
Weibo Mesh 中的高可用策略,支持一般的常用策略,比如 Failfast,Failover 等,負載均衡支持權重輪巡,根據權重輪巡、隨機等常用策略。當然也可以定制自己的 HA/LB 策略。
Weibo Mesh 中推薦采用的高可用策略是 Backup Request,又叫雙發。雙發繼承自 Motan 框架,是我們探索出來的比較高效可靠的機制。它可以有效解決長尾問題,同時能提升系統吞吐量。
傳統解決接口超時問題可能通過重試,在一次請求發送之后等待指定的超時時間,如果沒有返回則再請求一次,最差情況下要消耗 2 倍的超時時間。
而雙發機制則不然,在發送一次請求后等待 P90(在 T1 時間內有 90% 的請求都能返回則稱 P90=T1,通常系統的 P90 和程序設置的超時時間相比小很多)時間。
如果請求沒有返回則在此刻再次發送一次請求,在超時時間內,這兩個請求中取最快返回的那個。
當然,這里有個防雪崩機制,假如,超過一定數量的請求(比如 15%)都在進行雙發,則認為服務整體有問題,會自動停止雙發。實踐證明,雙發機制的去長尾效果非常明顯。
③節點抽象
Endpoint 是調用方 Mesh 到對端 Mesh 的調用單元。當我們啟動 Weibo Mesh,在初始化 Cluster 的同時,也會對 Endpoint 進行初始化,綁定 Filter Chain,并為每個 Endpoint 保持一定數量的長鏈接供選擇調用。
當然這里還會有一些細節,如果某個節點的調用失敗,計數超過一定閾值則自動摘除節點,并進行定期探測等待可用,再重新加入可用節點列表。
④Motan2 傳輸協議
Weibo Mesh 整體沿用了 Motan 的協議設計,并進行了升級。
Motan 支持 Java 的序列化,當時考慮的是 Java 間相互通信,但是考慮到跨語言通信及未來擴展需要,我們把協議設計分成序列化協議與傳輸協議。傳輸協議負責把序列化后的數據進行傳輸,序列化協議是跨語言的關鍵。
Motan 傳輸協議是典型的三段式:
Header
Metadata
Body
Header 中會標記序列化類型,消息類型(心跳還是正常請求),可以定義自己的 PB 序列化或是自研的 Simple 序列化。
在 Metadata 中會有一些方法名、屬性名、用戶參數;在 Body 中存放的是經過序列化后的請求/響應體。
Simple 序列化:Simple 設計比較簡單實用。目前 Simple 序列化支持了基礎類型,包括 Bool、String、Int、Float,當然它還會支持一些組合類型,例如 String、Bool 組合成的 Map,Array 等。
上圖示例,type 是一個字節的數據類型,比如 Bool、String,接下來是字節長度,接下來是 UTF-8 字節流。Content 中可以進行嵌套,下方就是進行嵌套的例子。
協議轉換過程:從協議層面看 Weibo Mesh 請求流轉是調用方通過函數調用 Client,然后經過 Motan2 傳輸協議以及 Simple 序列化后,經過本機 Mesh,Mesh 層再轉發給對端的 Mesh。
對端 Mesh 上層可能是任意一種形式的服務,比如非 RPC 服務,所以這里我們有個 Provider 模塊,可以代理HTTP/CGI等非標準 Service Mesh 服務,它能把這些服務導出成一個具有 Motan 協議的 RPC 服務。
通過 Provider 屏蔽了 Server 端服務的真實協議。Provider 外面是標準的 Motan 協議服務,內部是原有協議的服務,這樣對 Server 端來說,遷移到 Weibo Mesh 成本極低。
Weibo Mesh 控制面
控制面主要分兩方面:
①策略擴展
Cluster 和 Endpoint 都有相應的 Filter Chain,他們實現了不同緯度或者粒度的調用控制策略。
Filter Chain 包括訪問日志記錄、Metric、熔斷、限流、降級等。折中調用效率和耦合程度,它們都是以插件形式存在于 Weibo Mesh 中,也可以自由定制 Filter 策略及調用順序。
②流量調度
Weibo Mesh 的流量調度基于注冊中心。注冊中心不僅為 Mesh 提供了服務的注冊和發現,也提供了服務的配置下發,Mesh 在訂閱注冊中心的同時,也需要訂閱相關的配置項。
比如我們把 A 機房的流量都路由到 B 機房去,我們在 Mesh 只要支持這條指令就可以。
生產實踐
典型場景
上圖是網關,Mesh 在微服務架構中的整體分布圖。一般情況下網關架設在服務邊緣,邊緣節點主要把控宏觀的流量調度控制問題。
在內部,各微服務之間構建 Weibo Mesh,來有效提高服務間通信質量、可觀測性等要求。
遷移成本的考量:
真正將 Service Mesh 引入到業務場景中時,需要考慮一些問題點,比如業務部署模式是非云,混合云還是云原生?像微博是混合云,場景不同,因此架構也不盡相同。
Weibo Mesh 要適配注冊中心。
各語言要適配 Client,目前已經支持 PHP/C++/C/Python/Lua 等主流語言,Java/Go 原生支持。
要適配相應的 DevOps 建設。需要相應的監控/統計等平臺支撐,任何架構改造都要有足夠的 DevOps 支撐。
接下來為大家介紹 Weibo Mesh 正反向代理實踐。
正向 Mesh
上圖是 Weibo Mesh 場景下的正向代理流程。Server 端服務進行注冊,被調用方訂閱到,調用方請求經過 Client,再經過本機 Mesh,最終到對端的 Mesh。需要注意的是虛線部分是故障轉移的流程。
假如本機 Mesh Agent 掛掉,Client 會通過服務發現回來的節點快照選擇可用節點進行調用,達到故障轉移的目的。
反向 Mesh
上圖是 Weibo Mesh 場景下的反向代理流程。一般我們的服務類型是 HTTP/CGI,或者其他私有協議。
反向 Mesh 的亮點在于,不需要 Server 端做任何架構的改造,直接架 Weibo Mesh 就可以了。
Mesh Agent 通過 Provider,將原有協議導出成 Motan2 協議的服務對外進行暴露,只需要把導出的服務注冊到注冊中心即可提供服務。
同時也不會影響原有服務的提供。這里如果你需要把私有協議導出成 Motan2 協議服務,可以自行擴展開發。默認支持 http/php-cgi 服務的導出。
反向 Mesh 特色:
提供 HTTP/cgi provider,可定制擴展。
HTTP 框架自動轉 RPC,業務無需開發新 RPC 框架。
Mesh 對 Server 改造無侵入。
總結
治理模式的差異
傳統服務調用,中間可能經過網關或者 RPC。服務治理只能存在于一端,一般在 Server 端進行服務治理。
最后,給大家推薦一個Java進階內推交流群851531810,不管你在地球哪個方位,不管你參加工作幾年都歡迎你的入駐!(群內會免費提供一些群主收藏的免費學習書籍資料以及整理好的幾百道面試題和答案文檔!)
但是 Mesh 服務,由于 Agent 本機部署,封裝了服務治理,可以實現 Client 端或 Server 端的雙向治理,這是 Mesh 服務的一大特色。
Weibo Mesh 優勢
實戰效果如下圖:
上圖可以看到,Mesh 服務的 Client 端 RT 曲線逼近 Server 端的 RT,這說明點對點的 Mesh 調用,由于沒有中間層的損耗,再加上合適服務治理手段,兩端性能也比較接近。而 HTTP 服務則有較多的中間層損耗。
右圖可以看到雙發的 p999 曲線相對比較直,這說明雙發起到有效削長尾功能,間接也對系統性能有提升。
Weibo Mesh 集群
目前,微博內幾個核心業務之間調用已經 Mesh 化,并經歷過重大事件以及春晚的考驗,支撐流量還是相當大的。
和 Istio 的區別
從控制層面看,Weibo Mesh 把類似 Istio 中的 Mixer 和 CA 的功能以插件化的形式放到 Filters 里面。
Istio 服務需要通過 Pilot 來做服務發現,而 Weibo Mesh 是直接通過注冊中心,Istio 用 Envoy 做 Sidecar,而我們基于 Motan 打造了全新的 Agent。
Istio 有一個特色,上面每個模塊都可以理解為一個微服務,都可獨立拆分部署。
但是 Weibo Mesh 為了效率和內部落地的方便,更多的進行了插件式耦合,整體性能相比 Istio 也會更好。
上圖可以看到 Istio 通過云平臺適配各種 API,來進行服務發現,Weibo Mesh 則是適配注冊中心。
Istio 更強調依據容器層面的發現(直奔云原生),Weibo Mesh 則可支持通用注冊中心比如 Consul、ZK 等。
Weibo Mesh 通過 Client 攔截 Mesh 請求,模塊化耦合部分功能。高定制化時,并不能對服務做到完全透明。而 Istio 通過 IPtables 流量攔截實現了業務完全無感知。
WM 進行中
我們知道 Mesh Agent 并不關心代理轉發的是什么服務,所以就有一個新方向,即資源服務化,讓資源存儲層也能進行服務化。
Weibo Mesh 解決跨語言服務化的思路也同樣適用于服務與資源之間的調用問題。微博服務有很多資源依賴,MC、Redis、MySQL、MCQ 等。
我們可以在資源層架設 Agent,同樣可以達到資源即服務,也就是泛服務化。目前我們內部也已經有基于 Weibo Mesh 的資源服務化使用場景。
WM 未來發展方向
未來 Weibo Mesh 主要有兩個方向,一個是繼續推進云原生,一個是在易用性方面繼續打磨。
Weibo Mesh 打通云平臺和注冊中心推進云原生,結合容器編排在服務治理上進行優勢互補。
此外,我們也會積極努力推進,讓 Mesh 整合進 L5 這一層。我們還會繼續進行探索解決業務方接入不方便的地方,比如說更加方便的流量攔截方式;更廣泛的語言支持…
Weibo Mesh 始終推崇落地簡單、功能高效可靠,隨著 Mesh 更大規模的推廣,場景越來越極端,性能要求越來越高,我們在這方面也會持續打磨。歡迎大家一起加入 Weibo Mesh!
最后,給大家推薦一個Java進階內推交流群851531810,不管你在地球哪個方位,不管你參加工作幾年都歡迎你的入駐!(群內會免費提供一些群主收藏的免費學習書籍資料以及整理好的幾百道面試題和答案文檔!)