阿里技術專家詳解Dubbo實踐,演進及未來規劃

Dubbo整體介紹

Dubbo是一款高性能,輕量級的Java RPC框架。雖然它是以Java語言來出名的,但是現在我們生態裏面已經有Go、Python、PHP、Node.JS等等語言。在GitHub上,https://github.com/dubbo 下面已經有很多生態相關的東西。

Dubbo是一個RPC框架,它和所有的RPC一樣,有一個最小運行子集,它需要Provider、Consumer,以及一個服務註冊發現相關的東西,在Spring Cloud裏面是叫服務註冊發現,在Dubbo裏面我們叫它註冊中心(後面講到東西我們都以註冊中心來進行說明)。

簡單介紹一下Dubbo的整個啓動過程:

  • Provider導出一個服務,這個服務就是可被調用的;

  • 第二步,往註冊中心註冊這個服務;

  • Consumer這端會來訂閱相關的服務,如果註冊中心裏面,Provider列表有變化的話,它也會得到通知;

  • Consumer會根據一定的路由規則從註冊中心拿到Provider列表,再根據一定的負載均衡策略,精確地調用到某臺Provider上去。

這就是一個簡單的一個RPC的調優過程。

Dubbo在2011年就在GitHub上進行了開源,經歷了很多年的發展,整個社區一直非常活躍,現在GitHub上Star數已經高達23K+,Fork數16K+。

在2018年2月份的時候,阿里巴巴已經把Dubbo的項目捐獻給了Apache社區,希望更多人能夠參與到Dubbo開發中來,希望依靠集體的智慧讓Dubbo變得越來越好。現在Dubbo的committer,外部開發者的人數已經多於阿里巴巴開發者,包括微店,網易雲音樂,考拉,韓都衣舍等等。

Dubbo因爲開源這麼多年,積累了較多的用戶,包括很多互聯網的企業,包括阿里巴巴,考拉,滴滴等互聯網企業;還有很多中字頭企業,中國電信,中國人壽,中國工商銀行;還有一些比較傳統的企業。

Dubbo的實踐和演進

Dubbo服務註冊

背景知識介紹

在RPC整個鏈路中,需要的元素有Provider、Consumer,以及註冊中心(中間Zookeeper是作爲註冊中心來使用的)。整個註冊過程如下:

  1. Provider會把一長串URL(dubbo://xxx的字符串)寫入到Zookeeper裏面某個節點裏面去。

  2. Consumer的註冊也是類似,會寫到Zookeeper裏面某個節點(Consumer寫入的原因,是因爲OPS服務治理的時候需要實時的消費者數據)。

  3. Consumer發起一個訂閱,訂閱相關的服務。

  4. 當某個服務的Provider列表有變化的時候,Zookeeper會將對應的變化通知到訂閱過這個服務的Consumer列表。

從圖中我們可以看到Provider端的URL非常長,特別是當一個服務有大量方法的時候。Provider端的URL會先從Provider到Zookeeper,再往Consumer傳遞,這樣導致了單次傳輸的網絡開銷比較大。

那麼再來看一下集羣的情形,圖中左邊有N個Provider,右邊有M個Consumer,那麼Provider發佈的時候,會遇到什麼情形呢?Provider每次發佈它會先下線再上線,所以每個Provider發佈的時候,Provider會發送兩次通知,也就是發送2N次;接收數據方有M個Consumer,最後算出在整個網絡裏面的推送數據的次數是2N×M。

案例

來看一個真實的案例,在杭州有一家中等規模的電商公司,公司內部有4000+個服務,以Zookeeper作爲註冊中心,Zookeeper有100w個節點,在發佈日的時候,公司內部網絡的網卡被打爆了,進而導致服務變更的推送失敗,新的服務註冊也失敗。整個集羣基本上處於不可用狀態。同樣的也收到了一些中小公司的反饋,每次在發佈的時候,網絡也會有個抖動。

分析一下爲什麼會出現這種情形。

Zookeeper的100萬節點中,大約有10萬個Provider節點和50萬個Consumer節點。按照前面的算法,在所有Provider同時發佈的極端情況下,有2×10萬×50萬次推送,也就是說會產生1000億條的數據推送。針對每次推送的數據進行了一個統計,每條URL大小大概有1KB,那麼計算出來的極端的推送數據量是1KB再乘以1000億,已經是100TB的級別了。

上面說的是極端情形,就算是發佈日也不可能同時進行發佈:有的應用發佈日不發版本,不同應用不可能同時發佈,同一個應用也需要分批發布。假設同一時刻發佈的量在千分之一,那麼推送的數據量也在100GB,所以出現發佈日的時候間斷性地網卡爆掉的現象就不足爲奇了。每次發佈的時候,都會想着要跟別的應用發佈時間錯開,爭取單獨發佈,作爲程序員還要糾結這個事情真是一個悲劇。

案例分析

來分析下現在的問題和需求:

首先,根據上述案例中的數據分析得知,性能出現了問題。推送的數據量非常大,存儲的數據量大,網絡傳輸量大,服務推送延遲,網卡堵塞,服務註冊不可用。

接着對Provider端那個很長的URL進行分析之後發現,不需要把整個URL寫到註冊中心裏,只需要把IP的端口寫進去就可以了,因爲只有IP的端口需要實時變化。把其他信息放到一個類似的KEY-VALUE結構的持久化存儲裏去,而且這個KEY-VALUE結構只要是應用級別就行了,節省了大量的存儲空間。

社區中對服務測試的需求非常強烈。要支持服務測試需求,就需要知道調用的服務方法名,入參出參的詳細信息。所以這部分信息也是需要存儲下來的。但是這部分信息非常大,每個服務中可能有10多個方法,每個方法可能有三四個方法入參,入參和出參的完整數據結構往往非常複雜。這部分數據信息也叫做服務的元數據信息。

首先來看一下怎麼解決性能的問題。主要有兩種方式可以解決:

  1. 怎麼減少當次的註冊量,就像前面分析的,只存儲IP的端口到註冊中心;

  2. 是否可以減少推送的次數,現在推送次數太大了。

減少單次推送量

查看上圖可知,Provider端URL還是很長,期望簡化往註冊中心註冊的信息;同時服務測試需求,又同時期望能將更豐富的元數據信息進行持久化的存儲。

Provider端寫入的改造。Provider往註冊中心寫的時候,將整個數據的寫入分成兩部分:

  • 寫入註冊中心;

  • 寫入元數據中心。

註冊中心作爲服務的註冊和發現,更加關注數據的實時性和有效性(watch機制),整個URL中IP和端口就能判斷某個服務是否可用,其他信息都是相對固定不變的。所以註冊中心中,只需要存儲IP和端口。元數據中心中存儲URL中除IP和端口外的其他信息,加上服務測試需要的服務方法名,服務方法的出入參信息。元數據是一個KEY-VALUES的持久化存儲,是獨立於註冊中心的存儲,它不需要有watch的機制,而只需要提供持久化存儲。圖中使用的的KEY VALUE存儲是Redis,但是元數據中心定義了一套SPI,開發者可以去擴展,可以自己實現DB存儲,或者其他持久化存儲的方式。

Consumer端獲取Provider列表信息的改造。Dubbo之前的版本中,直接從註冊中心裏面獲取Provider端的服務信息,獲取到的信息已經是一個完整的可調用的服務信息。但是Provider端寫入改造之後,原有Consumer端獲取的Provider服務信息的方式不可用了。除了從註冊中心獲取到的數據之外,還需要從元數據中心裏拿到元數據信息,然後對這兩部分數據做一個Merge之後才能構建出完整的可調用的服務信息。

當前Dubbo2.7版本還沒有完全去除所有參數,而是採用先去除部分參數的方式來驗證;後續會逐漸迭代完善,同時在2.6.x版本中也會進行一些兼容方案的支持。

應用級服務註冊

上面的改造針對的是怎麼減少單次的推送數據量,針對的還是服務維度。期望中最理想地給註冊中心減負的方式是應用維度的服務註冊和發現,可以參考Spring Cloud體系下的Eureka實現。一旦實現這種方案,服務註冊中心就再也不會成爲RPC領域的瓶頸,而且可以認爲這種方案是服務註冊的終極方案

當然這種實現方式做的改動相對比較大,不僅需要將服務執行和運維完全分開,而且需要一定的架構體系改造來支撐具體服務的發現。到目前爲止還沒有形成成熟可靠的方案,團隊內部也只是在探討階段。

服務變更推送開關

所謂服務變更推送開關,就是針對任何的服務信息的變更,不進行推送。

到底哪種情形需要這種開關呢?阿里巴巴整個集羣的機器數非常大,所以宿主掛掉或者虛擬機掛掉出現的概率比較高。在每年雙十一的時候,大部分消費者都會去淘寶天貓上購物。在11月10號11點50幾分開始,大量買家在拼命地刷新購物車或者商品詳情頁面,這時候阿里巴巴內部的系統負載是非常高的,網絡負載也非常高。如果這時候,有一臺機器因爲宿主機掛了的原因而導致部分服務下線,這時候需要推送相關應用服務下線的變更給對應的服務Consumer。這時候就需要佔用網絡帶寬,可能對服務調用產生影響,進而還會對雙十一造成很大的壓力。所以這時候就希望有一個開關,能夠把整個服務推送關掉。

但是這時候也會帶來一些問題,當服務Provider不可用的時候,註冊中心沒有向服務Consumer推送變更通知,服務Consumer請求的時候可能會報錯,這時候的小部分服務出錯可以允許的;保證整個集羣上萬臺機器,特別是整個雙十一核心鏈路的穩定性纔是雙十一最重要的使命。

服務分組

在一個大的集羣環境中,在沒有路由規則的情況下,Consumer集羣會調用整個Provider集羣中的任何機器。服務分組,就是對Consumer集羣和Provovider集羣進行分組,將大的服務級分成幾個子集。

舉個例子,集羣中有8個Consumer實例,有8個Provider實例,按照正常流程Consumer這8個實例會調用Provider任何一臺,任何一個Provider的變更通知也會通知到這8個Consumer實例。但是如果對它進行分組呢,Consumer實例集羣分成A和B兩個組,Provider集羣也分成A和B兩個組。Consumer中A的組只能調到Provider中A組的服務;Provider的A組中的實例在發佈過程中,也只會推送到Consumer的A組中,而不會推動Consumer的B組。最終通過推送的範圍,來減少了推送的數據總量。

對於服務分組的的實現,這裏不做展開,本文後面再次講到服務分組的時候,會稍微展開陳述。

服務註冊中心

前面陳述的服務註冊相關的改造和方案,都是圍繞Dubbo等RPC進行的。接着來看一下在互聯網環境下,理想的註冊中心是什麼樣子的。(以下闡述只代表個人觀點)

CAP理論:現在大部分主流而且在使用中的註冊中心都是滿足CP的,但是在互聯網大集羣環境下,期望的結果是滿足AP的同時,能夠滿足最終一致性。在大集羣環境下,可用性往往比強一致性的優先級更高。以Zookeeper爲例,Zookeeper能夠爲分佈式系統提供協調功能的服務,默認提供強一致性的數據服務,但是它在某些情況下是允許Zookeeper是不可用的。列舉一個場景,Zookeeper Leader失效了,這時需要重新選舉Leader,而這個選舉過程需要30秒以上(數據來自於網上的文章),這段時間內Zookeeper對外是不可用的。

去中心化:Zookeeper是有Leader機制,往Zookeeper裏寫數據都是往Leader裏面寫,這個Leader其實就是一個單點。所以整個寫的過程是中心化的。而且Zookeeper對跨城跨機房的方案上,支持非常有限。

數據推送的強控制:期望對推送的有更加強的靈活性。還是以Zookeeper爲例,Zookeeper中有watch機制,每個數據節點發生變更的時候,就會往外推送變更的通知。但是作爲註冊中心,我們期望能夠控制它的推送頻率,針對新增節點只需要一分鐘裏面推送6次就可以了,每十秒推送一次,這樣可以合併一些變更通知,減少網絡數據請求的數據量。

容量:Dubbo是單進程多服務的方式來註冊服務的。這也就意味着註冊中心中需要存儲的數據量較大,所以要有足夠的容量來支撐這種場景。

那些註冊中心產品:Zookeeper作爲服務註冊中心的公司在減少,那麼現在有哪些方案,可以來替代呢?

Eureka是一個AP的應用,而且它是去中心化的。但是它有幾點不足:

  1. 在我們的內部的性能測試中,它性能表現非常一般,性能大概只有Zookeeper的60%左右。

  2. Eureka內有一種契約機制,它每隔30秒會發起一個續約的請求,如果3次沒有接收到,它纔會過期失效;如果一個服務非正常退出(沒有發起解約請求),那麼就存在這個超時的間隙期,服務是不可用的。所以在生產環境,對服務敏感的相關應用方是無法滿足需求的。

  3. Eureka是應用維度的服務註冊,當前的dubbo是服務維度的註冊,如果要匹配的話,需要大範圍改造。

  4. Netflix宣佈了停止更新Eureka 2.0。

Etcd是Zookeeper的升級版,它參考了Zookeeper的很多實現,同時進行了較多優化。Etcd的強一致性協議和代碼實現更加簡單,它的部署方式也更加簡單,它支持了Rest的方式進行相關訪問,它的性能相對Zookeeper來說也有了一定的提升。但是它還是一個CP的系統,它也是要求數據的強一致性,而犧牲部分的可用性。

Consul相對前面幾個產品來說,更加專注服務註冊發現本身,它是一個比較專業的服務註冊中心。Consul有了後臺管理頁面,它有了健康檢查,Consul原生支持多數據中心。但它的性能上有瓶頸的,它和Zookeeper和ETCD進行對比,它性能是稍微差一點的;同時Consul也要求數據的強一致性而犧牲部分可用性。

Nacos是阿里巴巴開源的一個產品,內部系統也在使用,它已經經受了一定流量和用戶的考驗。現在阿里巴巴集團內部的Provider和Consumer數量已經到達了億的級別,它現在能夠支撐上億級別的訂閱量,整體經受了一定的實踐檢驗。Nacos整體設計是去中心化的,而且設計上滿足AP和最終一致性,性能上和Zookeeper比較接近。

前段時間和網易考拉在溝通過程中也發現,他們也在做一個自己的註冊中心;新浪也有一個自己的服務註冊中心。所以許多大的互聯網公司,因爲定製或者差異化的需求,都在自研註冊中心。

配置中心

當前困境

應用開發者

Dubbo內部有一個配置文件叫dubbo.properties,這種配置方式和Spring Boot的application.properties是比較像的。每次新開發一個Dubbo應用的時候,應用開發者都需要去寫一大堆的配置到dubbo.properties中,包括註冊中心的地址,元數據中心的地址,應用級別的超時時間等等。當所在公司只有兩三個應用的時候,一個個應用單獨設置的方式是沒問題的;當業務快速發展的時候,應用數從2個變成20個應用的時候,那麼所在的技術團隊可能需要整理一份快速構建應用的文檔,供應用開發者參考使用,而且這個文檔需要及時維護更新。如果這時候還需要更改註冊中心地址(原來2個應用的時候,Zookeeper的地址用IP來快速實現,現在想換成域名了),意味着要去推動這20個應用的開發者,讓他們修改對應的配置,然後測試並且發佈。整個過程非常痛苦!需要有一種類似於Spring Cloud Config的配置方式來滿足集中式的配置方式,相當於一個遠程集中式的dubbo.properties。

Dubbo開發者

Dubbo 2.7以前的版本中,服務路由規則,服務治理規則的數據都是存儲在註冊中心中的。之前大部分用戶都選用Zookeeper作爲註冊中心,Zookeeper兼具了Key-Value的功能,所以之前的版本中運行起來是沒有問題的。 但是如果選用的註冊中心,不具有持久化的功能,這時候的路由規則和服務治理規則就沒地方存儲了,整個系統就玩不轉了。作爲Dubbo開發者,期望將服務治理和服務路由規則分開存儲到一個集中式的Key-Value存儲中。

要解決上述兩個痛點,需要在Dubbo中引入一個遠程的集中式的配置中心,這個配置中心存儲了遠程的dubbo.properties,路由規則,服務這裏規則等。

應用架構師

舉個場景,一個公司的所有應用已經引入了ETCD作爲自己的應用的動態配置管理,但是在引入Dubbo以後,Dubbo中又有幾套對應的動態配置可供選擇,如Nacos、阿波羅,Zookeeper。這就要求公司層面需要維護兩套動態配置的Server,這個成本比較高,而且增加了系統的穩定性的風險。對於架構師來說,需要Dubbo能支持ETCD的動態配置。

解決方案

圖中分成上下兩部分,下面黃色部分就是它的一個存儲;上面的整個部分是Dubbo內部實現。上文中所講的動態配置,在Dubbo中定義爲配置中心。

在實現層面,在Dubbo中定義了一層SPI,默認實現的Zookeeper,Apollo,Nacos。應用架構師去擴展這個SPI就可以完成ETCD的定製,這樣就能達到和原有的應用中使用ETCD方式兼容。

對於運維工程師來說,原來的一個註冊中心的地址變更要推動每個應用開發者去做變動,應用開發者非常煩,運維工程師很吃力。現在只需要在遠程的dubbo.properties裏進行統一去升級,然後通知相關的應用開發者進行一些適當的驗證。

因爲已經定義了配置中心的API,Dubbo開發者直接調用對應的API來實現服務規則和路由規則的存儲。

三個中心

三個中心就是前面講到的註冊中心,配置中心,元數據中心。

期望的使用方式:Provider先去配置中心裏獲取註冊中心的地址和元數據中心地址,再根據拿到的註冊中心地址去對應的註冊中心註冊服務,根據拿到的元數據中心地址寫入元數據信息到對應的元數據中心Server。Consumer和OPS也是類似的。

通過配置中心這種集中式的配置方式,可以讓開發者從原來煩瑣的配置中解脫出來,讓它更聚焦於業務的開發,而不需要關注框架層面的東西。

路由規則

路由規則組合

Dubbo路由規則,按照覆蓋範圍可分爲應用級別,服務級別,方法級別路由規則;按照功能緯度,可以分爲黑名單,條件路由 ,TAG路由規則。大部分路由需求都是可以通過組合來實現的,如應用級的黑名單可以通過應用級別+黑名單路由規則方式組合。

全鏈路灰度發佈

某產品新開發了一個新特性,想進行A/B Test,讓部分用戶開放新功能體驗;或者產品在迭代過程中,想進行下改造功能的灰度驗證。在當前微服務的架構體系下,一個新功能往往依賴整個調用鏈路的上下游一起完成。所以這兩種新功能的驗證,基本不可能在單機上完成,往往需要服務鏈路的上下游一起隔離出一部分機器進行驗證。在這裏,稱爲全鏈路灰度發佈驗證。

來看一種最簡單的場景。客戶在瀏覽器端發起一個HTTP請求,這個請求會根據一個負載均衡策略訪問到一臺web服務器(30.5.127.44),這臺機器會調用服務A集羣,服務A集羣會調用服務B集羣。業務開發者開發了一個新功能,想在線上驗證功能的正確性,但是又不想原有的功能受影響。也就是說想從服務集羣裏拿出少部分實例去驗證線上的功能。假設下需求,希望總用戶的千分之五的用戶能夠走到新功能的流程,幫助驗證新功能的正確性。

  • 從服務A集羣中選出一臺機器(30.5.120.16)作爲灰度驗證的機器,從服務B集羣中選出一臺機器(30.5.128.66)作爲灰度機器。對選出的這兩臺機器打上標canary(金絲雀)。

  • 需要在Web服務器運行的代碼邏輯中,增加邏輯:獲取到用戶的UserId,UserId對1000求模之後小於5的,在Dubbo對服務A集羣發起請求之前帶上Tag=canary(在Dubbo中是通過設置Attachment來完成)。

  • Dubbo自帶的Tag路由規則會做以下事情:Dubbo會先拿到要調用服務所在的應用名;再根據應用名+Tag路由規則的名稱canary,去獲取到對應的機器列表,Web服務就拿到了30.5.120.16這臺機器;Dubbo根據拿到的機器列表依據負載均衡策略發起請求。相應的Web服務器中沒有打上標的機器,會訪問到其他機器(30.5.120.26),而不會訪問到已經被打上標的機器。Tag路由規則,完成了對相應Provider和相應Consumer端的隔離。

  • 通過Tag路由規則已經解決了Web集羣到服務A集羣這裏面的鏈路,但是怎麼解決服務A集羣到服務B集羣的Tag的傳遞呢?現在比較流行的一些全鏈路跟蹤的產品可以幫我們做到,如Open Tracing,Zipkin。我們以Zipkin爲例,通過Zipkin實現Dubbo的Filter可以把這個標從Web集羣傳到服務A集羣再傳到服務B集羣,整個鏈路都可以傳遞下去。

  • 整體調用鏈路總結。滿足灰度驗證的用戶鏈路:web服務 -> 30.5.120.16 -> 30.5.128.66; 不滿足灰度驗證的用戶(不打標)鏈路:web服務 -> 集羣中30.5.120.16之外的機器 -> 集羣中30.5.128.66之外的機器。

通過上述步驟已經完成了全鏈路的灰度環境搭建,這種方式的應用範圍非常廣,可以按照自己的業務場景和需求進行一些調整來達到自己期望的效果。下面集羣中也有案例進行說明。

集羣

從集羣角度來看下,服務實例之間的隔離。假設一個Provider集羣有8個實例,Consumer-A集羣有4個實例,Consumer-B集羣有4個實例; Consumer-A集羣和Consumer-B都會調用Provider集羣。

服務分組:以Provider和Consumer-A爲例。將Provider分成左(1、2、3、4)和右(5、6、7、8)兩個組,將Consumer-A分成左(1、2)和右(3、4)兩個組。Consumer-A中左組只能調用到Provider中的左組,Consumer-A中右組只能調用到Provider中的右組,而不會調用到整個集羣的其他實例。服務分組除了能讓註冊中心減少推送的數據量外,還能減少Consumer和Provider長連接的數量,從而帶來一定的性能提升。

服務分組最簡單的實現方式,在Dubbo的Service和reference中配置中配置多個group,進行手動匹配。

更高級的服務分組實現方式,通過路由規則的方式進行動態匹配,路由規則中根據一定的規則(如根據Ip的最後位的奇偶數)將Provider和Consumer進行分組,然後路由規則裏去完成隔離。這種方式暫時還沒有發現較好的實現。

業務隔離:來看個現實的場景,阿里巴巴交易平臺承接的業務非常多,在新零售出來之前,所有的業務都是線上交易,在出現2分鐘的不可下單的時候,體驗糟糕但是還不會引起大範圍的騷亂。但是在盒馬鮮生線下購物的時候,如果出現2分鐘不能下單,那在排隊的消費者意味着要乾等兩分鐘,這是非常糟糕的體驗。

抽象下上面的場景,用更加產品化和技術化的方式來分析。以Provider和Consumer-A,Consumer-B爲例。Provider集羣的消費者非常多,包括Consumer-A,Consumer-B或其他Consumer集羣。因爲Consumer-B的業務非常重要,不想讓其他機器的故障,影響到Consumer-B的穩定性,所以Provider中來自於Consumer-B的流量需要進行隔離。業務隔離的實現方式,可以採用Tag路由規則的方式來實現。對Provider集羣的7,8機器打上標-BTag(即路由規則,可以通過OPS打標),然後在Consumer-B集羣中調用Provider之前setTag=BTag (在Dubbo中在attachment裏設置tag值)。

灰度環境

單機灰度的話,只要在發佈的時候,可以單臺機器發佈就可以。

全鏈路灰度,需要在整個集羣中圈出一批機器,如從Provider,Consumer-A,Consumer-B集羣中選出3號機器作爲灰度環境。全鏈路灰度的實現已經在前面說明,用Tag路由實現。

服務測試

Dubbo服務測試

Dubbo在啓動時,會導出服務,讓服務是可被調用的;同時它還會向元數據中心寫入元數據信息(包括服務方法的方法名,路參,出參等信息)。

服務測試是在Dubbo OPS後臺中的功能。服務測試業務流程:先去元數據中心獲取元數據信息;在頁面中展示服務的結構體,等待用戶輸入;用戶輸入參數信息;Dubbo OPS後臺根據元數據信息和用戶輸入的參數構造出服務調用的入參,向相應的Provider發起泛化調用。泛化調用被較多的網關係統使用。

Swagger整合

除了服務測試功能外,還需要:

  • 文檔功能。自動生成文檔,生成的文檔是可視化的,而不是JSON等文件格式。

  • 自動化測試。

Swagger可以滿足以上需求。但是Swagger和SpringMVC結合緊密,SpringMVC Rest接口加上註解之後,可以快速整合Swagger。

要讓Dubbo能夠通過Swagger方式生成文檔和進行自動化測試,需要做兩個事情:

將Dubbo接口形式轉換成Swagger文檔。Swagger是有文檔規範的,只要將接口形式轉換成Swagger約定的格式,就可以滿足Swagger文檔的形式進行輸出。

Swagger服務測試功能。外部HTTP請求到一個Controller,Controller需要將HTTP請求轉換成Dubbo請求,包括參數的映射和服務的映射。

服務治理

Hystrix停更

Hystrix停更了,在GitHub官網上推薦了Resillence4j,阿里巴巴也開源了Sentinel。這裏進行一個簡單的比較。

Hystrix的兩塊功能,隔離和熔斷,能滿足大部分需求但是停止更新了。

Resillence4j要求JDK8及以上,對function編程更加友好。

Sentinel 在阿里內部使用的範圍非常廣,已經經受住了一定的考驗。每年雙十一在買東西的時候,如果出現一個頁面上顯示系統繁忙請稍候重試,或者顯示人太多了請排隊,這時候其實就是Sentinel在後臺發揮作用了。Sentinel OPS這塊做得非常好,達到了開箱即用的標準。

服務治理清單

不要設置應用級別重試

在Consumer端設置重試,必須保證Provider端多次調用是冪等的。

設置應用級別的重試,會讓已經壓力倍增的系統雪上加霜。舉個例子,Provider系統的線程數是200,當Provider某個服務出現問題,導致RT從200ms變爲了3500ms;Consumer因爲設置了默認重試且重試次數爲3,這就會導致Provider線程池很快會被耗盡。

所以,默認不要設置應用級別的重試,對有業務需求的服務單獨設置重試的規則,並且保證Provider端服務的冪等性。

設置超時時間

設置超時時間,能夠防止系統雪崩和資源耗盡。一個Consumer調用Provider的時候,Provider 需要3秒處理完業務邏輯之後返回結果,Consumer默認是同步調用,需要某個線程同步阻塞等待3秒,也就是說如果沒有超時機制,很容易將Provider的問題傳遞給Consumer並且不斷往上傳遞。如果Consumer設置了超時時間200ms,Provider加入需要3秒處理完結果,但是不會將問題傳遞給Consumer。

建議的超時時間是一百毫秒到兩百毫秒左右,對於特殊業務進行特殊設置。

隔離

隔離包括實例隔離和線程隔離。實例隔離,就是前面講到的服務分組和業務分組,通過實例隔離達到問題和影響面的隔離。

線程隔離,可以分爲靜態隔離和動態隔離。靜態隔離,首先通過一定的分析方法找出一些比較慢的方法,或者甄選出業務上比較重要的服務方法;再對這些服務或者方法單獨設置線程池以及對應的線程個數。動態隔離是在Dubbo應用運行態的時候,自發地調整線程池的隔離。Dubbo應用裏默認的線程數是200個,200個消耗完之後,新的請求進來就會返回線程池滿的異常。這時候Dubbo內部會對運行中的服務方法進行統計,統計出併發線程數>8,RT>300ms(假設的一個指標)的服務,把這些服務扔到獨立的線程池裏去完成,後續這些服務的執行都會由這些新建的線程池的線程執行,其他服務仍然在這200個線程池裏面執行。當這些隔離的服務方法運行一段時間後,它的RT變得正常了,那這部分獨立出去的線程池可以被銷燬,這些服務方法可以重新由原來的200個線程執行。整個過程的調整是動態的。整個動態隔離的機制和Hystrix的線程隔離有些相同的含義。

治理工具

每個微服務實踐的時候都會講到。微服務最佳實踐裏面,強鏈路跟蹤,限流,降級、熔斷等,都可以在系統裏引入,進而保證系統的穩定性。

系統可驗證

系統可驗證主要包含兩方面,第一個是環境是可被驗證的;第二個是通過一定的測試手段和方法來保證系統是可測試和可驗證的。

環境可被驗證,有些場景需要支持單機的灰度,有些場景需要全鏈路的灰度。

測試方面:在系統上構建接口級別的服務測試,自動化測試,支持全鏈路壓測。通過服務測試和自動化地執行來增強系統的正確性測試;通過全鏈路壓測,來判斷全鏈路的瓶頸在哪裏。

Service Mesh

Service Mesh在2018持續火熱,阿里巴巴和螞蟻都在這一塊有佈局。現在阿里內部主要在兩個場景中去做嘗試,第一個是跨語言。阿里大部分語言是Java,但是有少部分是C++,還有部分NodeJS,需要Service Mesh去解決跨語言之間的調用。第二個是異構系統。阿里巴巴收購了一些公司,但收購進來公司的技術棧和集團內部不一致,它可能是Java語言,但是使用的Spring Cloud的微服務體系,還有一些公司沒有使用Java語言,需要通過Service Mesh來解決這種異構系統之間的調用問題。

從實現方式上來說,阿里沒有重複的造輪子,控制層這一塊(也被稱爲sidecar),是在Envoy上進行了一些擴展,實現了一個Dubbo Filter,現在這部分代碼已經被捐獻到了Envoy的社區。數據層實現方式是對Istio 做了一些擴展和定製。因爲Istio有一套默認的服務發現,服務治理的產品,但阿里巴巴有自己的服務發現,動態配置管理,服務治理的產品方案。在數據層,會將Istio和阿里巴巴中間件的產品做一些整合,來滿足需求。

從部署結構上看,Dubbo應用和對應的Envoy實現是部署在一臺機器上(虛擬機)的,只是以兩個進程的形式存在。Dubbo應用需要調用Spring MVC應用中的服務,每一次發起調用的時候,Dubbo應用會首先調用到同一臺機器上的Envoy進程,再調用到另外一臺機器上的Envoy進程,另外一臺機器的Envoy進程再調用SpringMVC應用。整個調用過程多了兩跳。

阿里巴巴已經在鹹魚的一些場景上在做Service Mesh的驗證,同時程序和架構也在持續優化過程中。

Dubbo現狀和未來

當前工作

核心特性

針對2.7之前存在的若干異步問題進行了優化。在Dubbo2.7之後,開始全力擁抱JDK8。所以2.7版本將基於JDK8 中的CompletableFuture做出一些針對性的增強來支持異步,類似於Promise方式。

優化服務治理參數配置,升級服務路由規則,同時對應的OPS也進行了相應的升級。Dubbo2.7之前的路由規則對應關係一個服務可以對應多條規則,優化之後一個服務只能對應到一條規則;新增了前文講到的Tag路由;服務治理參數,路由規則的數據存儲都將使用配置中心。

社區裏面分支演進分成2.6版本和2.7版本。2.7版本主要有一些新功能的迭代,2.6以維護爲主。如果2.7裏有些功能可以被2.6借鑑的話,也會往2.6裏面疊加。

Spring Boot

新增了一個工具頁面,用於快速構建Dubbo的Spring Boot的應用。這個參考了Spring Boot的模式。

在Dubbo體系下,有一個Dubbo Spring Boot工程來支持Dubbo+Spring Boot的整合。到目前爲止支持Dubbo2.6.X版本,支持Spring Boot 1.5.x和2.0.x。因爲Spring Boot的1.5和2.0的分支差距比較大,所以Dubbo Spring Boot也維護了兩個版本。後續Spring Boot 1.X會在2019年停止更新。

Dubbo OPS

Dubbo OPS進行了全新的升級,有了一個新的UI,合併了Dubbo Admin和Dubbo monitor兩個應用,而且整個OPS用了Spring Boot工程結構,從而真正達到了開箱即用。Dubbo OPS能夠同時支持2.6和2.7的版本的運行,對新功能進行了相應的配置支持。

開源建設

Dubbo捐獻給了社區之後,重新搭建了新的官網,新的中英文文檔,有了中英文博客,整個社區現在非常活躍。在這半年多依賴,和一些深度使用Dubbo的客戶做了一些交流,如工商銀行,考拉等等。今年舉辦了5場Meetup,包括杭州,成都,深圳,北京,上海,吸引了大量的開發者參與。

生態建設

  1. 正如前面所說,在多語言方面,社區引入了PHP,Go,NodeJS,Python等。

  2. 對現有的一些生態組件進行持續升級和維護。

  3. 引入了一些新的擴展組件,包括SkyWalking,ETCD等等。

未來規劃

社區投入

社區持續投入,包括PR,Issue跟進,優秀博客和文檔的持續輸出。當然整個運作形式是根據Apache的方式進行運作,而Apache溝通的最主要形式就是郵件,所以各開發者可以訂閱Dubbo的郵件列表進行持續跟蹤。

持續推進Dubbo Meetup和客戶交流。

功能增強和Issue跟進

持續功能增強和優化,包括前面的註冊中心的優化,路由規則的持續增強和優化。現在Dubbo的committer中,阿里只佔了小部分,其中來自於網易音樂和考拉,微店,韓都衣舍,有贊等公司的開發者也非常活躍。最近有一位印度的開發者,也正式成爲了Dubbo的Committer。

生態建設

因爲現在生態中,部分實現已經有了重疊,包括後續進來到我們生態體系裏的擴展也會造成同樣的擴展或者實現出現重疊,這時候會進行一些優勝劣汰。

Dubbo和SpringCloud關係,部分同學在選型的時候覺得要麼選Dubbo,要麼選SpringCloud,兩者互相排斥的。其實不是這樣的,這塊的詳細描述,可以關注公衆號:阿里巴巴中間件。裏面會有一些文章的描述和分析。

Dubbo 3.0

Dubbo 3.0的進展,比較受到關注。因爲涉及到Dubbo和HSF整合,以及一些新特性的開放,如reactive的引入。但是整個過程是非常漫長的,因爲兩個產品不可能完全融合,需要有一些特性存在。而且在完成之後,整個遷移的過程非常巨大。今年上半年,會有一個預覽版本,現在很大一部分人力已經投入到Dubbo 3.0的研發中。

Service Mesh

Service Mesh,現在還在測試階段,整體還未達到生產環境的級別。還需要不斷優化性能和不斷在各個場景中試用。


作者簡介

曹勝利,阿里巴巴中間件技術部技術專家。2010年加入阿里B2B中國網站技術部,先後在1688技術部,菜鳥技術部負責業務產品;曾負責阿里採購平臺的架構和服務化改造工作;目前在阿里巴巴從事應用容器和微服務框架的開發、實施以及效率提升相關的工作。關注分佈式架構、微服務,特別是Spring,Spring boot生態的發展。

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