Dubbo 實踐,演進及將來規劃

Dubbo 總體介紹

Dubbo 是一款高性能,輕量級的 Java RPC 框架。雖然它是以 Java 語言來出名的,可是如今咱們生態裏面已經有 Go、Python、PHP、Node.JS 等等語言。java

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

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

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

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

  • Consumer 這端會來訂閱相關的服務,若是註冊中內心面,Provider 列表有變化的話,它也會獲得通知;sql

  • 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,路由規則,服務這裏規則等。

歡迎歡迎學Java的朋友們加入java架構交流: 855835163

應用架構師

舉個場景,一個公司的全部應用已經引入了 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 分紅左 (一、二、三、4) 和右 (五、六、七、8) 兩個組,將 Consumer-A 分紅左 (一、2) 和右 (三、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,如今還在測試階段,總體還未達到生產環境的級別。還須要不斷優化性能和不斷在各個場景中試用

歡迎歡迎學Java的朋友們加入java架構交流: 855835163 羣內提供免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用本身每一分每一秒的時間來學習提高本身,不要再用"沒有時間「來掩飾本身思想上的懶惰!趁年輕,使勁拼,給將來的本身一個交代!  

相關文章
相關標籤/搜索