歡迎光臨
每天分享高質量文章

阿裡Apache Dubbo佈道師談Service Mesh技術

本文整理自2018杭州雲棲大會首屆開發者生態峰會呂仁琦的分享,來自“阿裡巴巴中間件”公眾號。

Service Mesh和Dubbo

Service Mesh這個“熱”詞是在2016年9月被“造”出來,而今年被稱為Service Mesh的關鍵之年,各家大公司都希望能在這個思潮下領先一步。今天我也分享下阿裡巴巴中間件在這方面的觀點、思考和實踐。考慮到有些人沒瞭解過Dubbo和Servicemesh,先簡單介紹下這兩個詞。Dubbo應該是國內最受歡迎的遠程服務框架,在Github上有超過2.1w的star數,也是阿裡巴巴分佈式架構互聯互通的核心所在。

跟Dubbo一樣,Service Mesh也是面向服務互聯互通這一問題域,是雲原生技術棧的核心之一;大家可以簡單理解Service Mesh就是雲原生組織定義的微服務架構解決理念。Dubbo是實現框架,如何融入Service Mesh理念就是我今天要分享的。

當前Dubbo支撐的阿裡分佈式應用內支撐萬級別的應用數,運行在20多萬的服務器實體上,每天呼叫量是萬億級別,這應該是國內最大的分佈式應用集群。挑戰主要來自三方面:

  • 首先, 數以萬計的應用意味著有以十萬級的服務,理順錯綜複雜的服務拓撲關係,甚至及時診斷某個異常呼叫鏈路,需要考慮海量資料的拉取分析,是非常有挑戰的,阿裡通過EagleEye鷹眼鏈路系統提供可觀察性和治理能力來解決;

  • 第二個挑戰是機房級別容災,阿裡的機房是分佈在天南海北,大家可以想象橫跨數千公里的網絡延遲會造成服務互通很大的影響,所以在保證一定恢復時間和一定資料容錯的情況下做異地多活是有巨大挑戰,阿裡通過支持異地多活的單元化架構解決;

  • 第三個挑戰是阿裡業務眾多,尤其像阿裡生態中的高德,UC,優酷等所使用的開發語言跟淘系Java是不一樣的,比如PHP,C,Nodejs,Dart等,要維護多個版本並保證各版本具有同樣的功能是成本比較高的;這個挑戰在雲原生的新一代理念下更具挑戰,畢竟。今天主題跟第三個挑戰是息息相關,能解決一定的問題。

  • 這裡講個大魚吃小魚的故事來簡單理解下雲原生:軟體會吃掉這個世界,也就是信息化不可避免,而開源會吃掉軟體,最終雲原生會吃掉開源。這正代表了雲原生理念的顛覆性,從商業軟體到開源到雲原生,環環相套,以體系化和層次化的方式推薦各個方面的開源方案和標準,這會極大降低企業級架構服務的技術門檻,是企業信息化之路的一大利好,當然也是進化方向。這個故事跟我們的主題–開發者定義軟體未來,是非常契合。

    雲原生: Cloud Native is Patterns with A complete and trusted tool kit formodern architectures

 

Service Mesh的sidecar樣式的對比

傳統形態下SDK代表著一個特定語言的庫,由應用和微服務框架共處一行程內,在發佈升級中共享生命周期。比較典型的代表是Twitter的Finagle,Google的Stubby/Grpc,阿裡巴巴的HSF/Dubbo。

Service Mesh下推薦的是右邊的Sidecar方案,Sidecar方案沒有引入新的功能,只是改變了原有功能的位置,以獨立的應用來存在,大家可以暫時以nginx來理解其網絡代理能力也可以。在這張圖中希望大家關註兩個信息: 


  1. 所有的sidecar形成邏輯網絡被稱為資料面,是業務服務的鏈路中是強依賴節點,承載了業務資料互聯互通的基礎;傳統的ops管控服務被稱為控制面,這部分跟傳統是大同小異。 

  2. 在sidecar形態下,網絡會增加兩跳,即應用與sidecar之間,他們之間的資料互通也是基於協議規範。

 

 

接下來從開發和運維兩個階段來分開比較:

  • 多語言支持方面:既然sidecar是獨立應用,用最合適的一種語言開發完成即可,就避免了需要針對不同語言的應用場景做不同的版本開發。當前阿裡選擇基於C語言的Envoy做二次開發來追求最小的footprint和性能,當然也曾經歷一些彎路,比如曾經用Java開發過一個sidecar,但最終由於引入JRE體量大和GC帶來的抖動等問題證明不可行。有必要強調的是:這裡說的是sidecar自身開發現在避免了多語言多版本的問題,而真要支持任意服務自由採用任意語言實現這一理想,是需要站在從業務到資料面再到業務的整個鏈路上的資料交互做思考。

  • 性能方面:sidecar情形下由於會增加兩跳,這兩跳是業務應用與sidecar的兩個行程之間的呼叫,這是本機,即便是經過優化,也是會增加行程切換以及資料轉換的開銷。經過我們的優化測試,在正常的業務訪問下,相比SDK形態下最多增加0.1毫秒的開銷,這在大多數業務情形下是基本無感知無影響。

再看運維階段的比較,一般SDK形態的服務框架都是只關心開發的訴求,對於如何運維都是不關心,而軟體生命周期中運維是最長的,如何從中間件角度解決更多的運維問題是非常有意義的。阿裡的中間件經常需要升級,以庫的形式升級時就需要業務方應用重新打包,這個推動業務方變更的方式是比較被動,而且周期很長。

當以鏡像為基本原子單位進行發佈部署時,阿裡的中間件SDK體量大概是200兆,需要與業務一起打包,這樣在業務應用升級時讓分發的包就顯得笨重,時效性相比sidecar形態就差一截。

總結下,sidecar具有兩個明顯優勢,一個是多語言開發維護成本低,另一個是獨立升級,當然代價是需要增加一點點的網絡延遲。至此大家是不是覺得Sidecar基本完美? 彆著急,需要大家再思考一個問題:SDK樣式下中間件組件會隨應用一起發佈,擁有完全一致的生命周期;而在sidecar樣式下,如何管理sidecar的生命周期?這裡可以拿無線耳機來舉個例子,無線耳機是獨立了,但必須獨立電源的驅動,所以充電是要的。是的,在大規模的集群中這個點會帶來不小的複雜性。

 

Service Mesh的三個關鍵技術點

我們對Service Mesh理解的三個關鍵技術點,分別是sidecar運維,資料面與控制面的集成,協議。

  • 先說sidecar的運維,這是個難點,也是為什麼sidecar方案以前沒有被廣泛應用的重要原因。前面說sidecar與應用現在成為兩個不同的行程,要考慮多個事宜,一是要考慮如何把sidecar與應用部署在一起,二是考慮業務行程或sidecar行程一方需要升級重啟時如何協同來保證請求的正常處理或轉發,即優雅上下線的問題。這些事宜考慮清楚並解決後,算是具備servicemesh的前提條件。當然,kubernetes解決了這塊的事情,提供了initiator類似插件的機制來對原子性的pod進行註入sidecar,並通過健康檢查機制來保證兩個行程的協同。簡單地也可以這麼理解:先把kubernetes容器調度平臺的實施是servicemesh的前提條件。

  • 資料面中的sidecar的服務治理能力則是其核心競爭力,包括負載均衡策略,路由,安全,權重等等,這些能力是以規則形式通過控制面來統一下發給資料面。在傳統微服務框架下資料面和控制面的集成是緊耦合,也就是資料面和控制面是一體的,舉例來說用了Dubbo框架,只能選擇Dubbo-Ops。而Envoy作為servicemesh思潮的帶領者,提出了一整套的API規範,Istio可以實現其xDS接口,阿裡巴巴也可以根據自己的架構設計實現類似的服務平臺。

  • 協議、協議、協議, 重要的事說三遍。sidecar和Dubbo的內核是網絡協議的處理器,而sidecar又是面向多語言場景的,所以自然協議處理能力是要強調的。先說下阿裡Dubbo當下向Mesh方向發展時遇到難點。首先我們的服務接口都是通過Java Interface描述,其次涉及的傳輸模型DTO也是Java POJO定義,最後協議也是私有的。這會導致跨語言比較難,而sidecar形態需要面向多語言,這些問題更是首當其衝。考慮到這裡有點稍微偏細節點,希望大家帶著如下問題來先思考下:業務應用到sidecar之間的資料交換要考慮什麼? Sidecar自身在處理網絡位元組流時又要考慮什麼?是的,首先業務應用最好都不依賴特定協議庫,也不依賴特接口定義庫;Sidecar自身處理資料時跟nginx很接近,但最好具備協議轉換適配的能力,比如把基於HTTP的請求轉換為Dubbo請求,就能輕鬆集成Dubbo遺留系統。

協議、協議和協議

既然協議在跨語言場景下如此重要,有必要稍微回歸下協議的歷史軌跡。看歷史一般是輕鬆有趣的過程,最重要的好處是能使我們頭腦清晰而不迷茫。

  • 我們先從2008年說起,很近也就10年,阿裡服務框架誕生這一年。當年各大公司還在炒作SOA思想的時候,阿裡在不清楚SOA思想的情況下根據自身業務訴求實踐擁抱了SOA的架構。阿裡服務框架一直是從三個層面來定義,第一RPC通信,第二是提供豐富強大的治理能力,第三就是基於容器隔離的運維能力,使得中間件可以獨立升級。這個理念直到今日都是非常先進,非常的贊。就像前面說的,Dubbo主要是面向Java領域的微服務架構解決方案,在以Java為主導的技術架構下是絕對首選,但因為其協議設計是私有特性,要想成為跨語言的協議標準是有一定難度。

  • 事實上,之前已經出現了很多通用的跨語言的服務集成規範。最早是91年的考吧,是分佈式物件訪問協議,2000年的SOAP是當年webservice思想下的協議,無論是考吧還是SOAP都是支持所有平臺和語言的一套規範,但是設計地比較複雜笨重,且性能存在一定問題。

  • REST是一種架構風格,相比SOAP的設計,有非常優秀的理念和最佳實踐指導,並且萬維網作為世界上最大型最成功的的分佈式應用是REST最好的證明。但跟SOAP一樣,REST跑在HTTP1.1上有性能瓶頸,這個也可能是當年阿裡服務框架沒有選擇REST規範的原因。額外提下,REST思想雖然很早就有,但事實上REST的規範在Java領域JAX-RS API 直到最近兩年在2.2版本下才算穩定成形,且越來越接近微服務框架。

  • 1996年的HTTP1.1在連接通道不支持多工復用,根本無法發揮TCP/UDP的網絡能力;而到了2015年HTTP2則解決這些,能夠最大限度的利用TCP層的網絡寬帶,且支持了streaming,push等交互樣式,這些跟很多的私有或專有應用協議幹得是一個事,但是標準化的大家都容易接受的事。這裡必須提一下,伴隨HTTP2而來的是grpc,原先Google早早推出了Protocolbuffer,但一直沒把自家stubby開源,我猜測最大的原因是不想grpc跑在一個私有協議上,而是在等HTTP2.

 

總結下來,協議技術一直在向著輕量級和標準規範化的方向發展。像SOAP,考吧這些重量級的不跨平臺的協議必然消失在歷史車輪里,私有或專有的協議也會向標準協議靠攏。在面向跨語言的場景下,有兩種的協議規範是大概率勝出,一種是REST,一種是grpc,兩者都是以HTTP為交換通道。

展開來講,在面向多語言的協議需要考慮三個層面。

  • 先從最右邊的會話層,幹得事是在tcp位元組流的基礎上形成交互樣式,比如 一對一的標準請求響應樣式,以及onway,一對多的streaming樣式。Dubbo在這一層是有擴展能力的,目前除了支持自定義的Dubbo-Remoting,也支持基於HTTP通道能力,我們覺得未來的趨勢是HTTP2,所以也會支持這塊.這裡在分享一句話跟大家一起思考,HTTP不是RPC,HTTP被翻譯成超文本傳輸協議,但不是傳輸層。

  • 再說展示層,幹得事是在真正的服務呼叫過程中,業務物件以何種形式被格式化,比如HTTP頭中的Content-Type就用於這個展示協議的描述,最常用的JSON,TXT,XML等。這一層對於sidecar來說,可以做透明處理,也就是說sidecar只需要解析出頭部信息,前提是要求業務應用把需要在治理時用到的一些欄位信息以字串形式放到頭部中。Dubbo當前是預設HEssion,跨語言能力比較弱,所以未來JSON是我們首選。

  • 最後,首先一個服務是乾什麼的,它的名字,方法,引數都是怎樣的,等等基本元信息是需要統一描述的,即便像是REST這樣基於URI,也是需要一種協議來定義,以前Dubbo是基於Java interface來定義,現在我們在多語言的mesh環境下是考慮向OpenAPI specification方向考慮,支持swagger。

我們相信在這幾個層面,尤其是會話層和應用層,用不多幾年一定會是標準化的,尤其是在雲原生的趨勢下。

Kubernetes下的集成

其實,Service Mesh在最近兩年流行最大的原因是雲原生理念的逐漸深入人心,從廣義角度看,能夠融入雲原生的微服務框架都能稱得上Service Mesh。談雲原生,肯定繞不開Kubernetes,所以我們在Dubbo Mesh的方案的第一個分享是在Kubernetes下的集成,標的是復用Kubernetes的基礎服務,從而使得Dubbo能解決Kubernetes環境下的微服務集成問題,同時能最大限度的利用Dubbo已有的功能。核心思路是兩點:

  • Dubbo應用在構建階段自動生成其deployment和service的宣告檔案。這

    個主要是解決Dubbo與Kubernetes的服務映射。

  • Dubbo地址註冊針對Kubernetes的擴展實現,通過Kubernetes的APIServer來拉取並監聽某個服務的podIP。這樣,在Kubernetes集群內,Dubbo服務就能在其podID的虛擬網絡內實現服務發現。

Dubbo協議的多語言集成

前面講了很多關於協議方面的東西,也為我們在Dubbo Mesh的方案的第二點分享是做了鋪墊,第二點的標的是Dubbo協議的多語言支持。核心思路是:

  • 積極兼容開源社區Envoy,這個使得Envoy上兼容支持Dubbo的私有。

  • Dubbo支持HTTP/2作為傳輸通道,這個是為了Dubbo的協議通道能力向更加開放更加標準規範的方向做努力。

孤立地看待Service Mesh其實和傳統服務框架,價值還不算大,甚至成本相對更高。這時候,當我們把Service Mesh設定到雲原生的背景關係中,就會發現不一樣的意義。

Service Mesh是雲原生理念的路徑地圖的第五步,如果沒有前面的容器化,CICD等四部,真正擁抱Service Mesh也只是空中樓閣。阿裡在這方面的實踐經驗是,Service Mesh的實施是需要結合軟體開發的整個生命周期進行統籌,從軟體在本地開發測試,到通過持續集成服務的自動化構建,再到以鏡像方式分發到倉庫並依托調度雲平臺的持續部署,最後持續監控。

 

Dubbo已經開源好多年,是非常符合雲原生這個原則,正向Service Mesh方向和雲原生理念上努力,為企業信息化做出一點貢獻。

 

總結一下

Dubbo Mesh是Dubbo在Cloud Native下的一種演進,這個演進是為了更加開放更加靠近標準協議規範的方向做的探索。通過分享希望大家能帶走三點思考。

  • Service Mesh的多語言方案其實是走規範化標準化的協議之路,這樣才能改寫多語言的訴求。

  • 建議大家根據實際業務場景來慎重權衡sidecar樣式下運維複雜性和收益回報。

  • 一定把Service Mesh設定在雲原生的背景關係中才具意義,離開了Kubernetes談Service Mesh的實踐是不建議的大躍進。

最後,希望大家可以參與共建Dubbo開源社區,謝謝。


推薦閱讀:

  1. 一大波精選架構技術文章來襲

  2. 架構師遇到這些技術瓶頸怎麼辦?

溫馨提示:

請搜索“ICT_Architect”“掃一掃”二維碼關註公眾號,點擊原文鏈接獲取更多電子書詳情

求知若渴, 虛心若愚

赞(0)

分享創造快樂