DUBBO——2.7大揭祕
目標:瞭解2.7的新特性,以及版本升級的引導。
前言
咱們知道Dubbo在2011年開源,中止更新了一段時間。在2017 年 9 月 7 日,Dubbo 悄悄的在 GitHub 發佈了 2.5.4 版本。隨後,版本發佈的很是迅速,Dubbo項目被重啓了,通過大半年的更新,在2018年2月15日,Dubbo 得到了 14 張同意票,在無棄權和反對票的狀況下,正式經過投票,順利成爲 Apache 基金會孵化項目。如今的Dubbo社區很是活躍,版本進度也很是的快。html
從上圖就能夠看出dubbo如今的活躍度。java
如今dubbo項目有如下幾個分支:git
- 2.5.x:該分支在近期投票決定再也不維護。
- 2.6.x:該分支如今還在維護中,包名前綴是com.alibaba,也是貢獻給 Apache 以前的版本。
- 2.7.1-release:一個臨時分支。
- 3.x-dev:將以 Streaming 爲內核,重點的改變在服務治理和編程模型上。具體我也尚未深刻研究,我也會跟蹤該分支的變更,敬請期待吧。
- master:目前版本是2.7.x,包名前綴是:org.apache,也是 Dubbo 貢獻給 Apache 的開發版本,接下來的分析也會在2.7.1上進行分析。
關注dubbo社區的朋友應該也知道在2019.3.23在南京舉辦了Meetup,其中有一個專題就是講2.7新特性介紹。我就在分享者的基礎上講解一下本身的理解。github
正文
(一)JDK版本
在所需的最小JDK版本從之前的1.6變成了1.8。redis
(二)包重命名
com.alibaba.dubbo - > org.apache.dubboapache
(三)異步支持優化
咱們知道dubbo協議自己支持三種發送請求方式:編程
- 單向發送:執行方法不須要返回結果
- 同步發送:執行方法後,等待結果返回,不然一直阻塞.
-
異步發送:也就是當我發送調用後,我不阻塞等待結果,直接返回,將返回的future保存到上下文,方便後期使用。在異步發送中有兩種方式分別是segmentfault
- future:當請求有響應後,經過future.get()來得到響應結果,可是future.get()會致使線程阻塞,future從RpcContext獲取。
- callback:設置一個回調線程,當接收到響應時,自動執行,不會對當前線程形成阻塞,自定義ResponseFuture支持callback。
2.6.x版本的異步方式提供了一些異步能力,包括Consumer端異步調用、參數回調、事件通知等。但當前的異步方式存在如下問題:緩存
- Future獲取方式不夠直接,只能在RpcContext中進行獲取;
- Future只支持阻塞式的get()接口獲取結果。
- Future接口沒法實現自動回調,而自定義ResponseFuture雖支持callback回調但支持的異步場景有限,如不支持Future間的相互協調或組合等;
- 不支持Provider端異步
具體的能夠參考該文章dubbo源碼解析(二十四)遠程調用——dubbo協議中的源碼分析來理解其中存在的問題。異步
那麼在2.7.x版本,因爲JDK版本升級到了1.8,引入了JDK1.8 中的CompletableFuture接口,CompletableFuture支持 future 和 callback 兩種調用方式。關於CompletableFuture怎麼被運用到dubbo中我會在後續的文章介紹。引入該接口後,作了如下優化:
- 支持Provider端異步
- 支持直接定義返回CompletableFuture的服務接口。經過這種類型的接口,咱們能夠更天然的實現Consumer、Provider端的異步編程。
public interface AsyncService {
CompletableFuture<String> sayHello(String name);
}
- 若是你不想將接口的返回值定義爲Future類型,或者存在定義好的同步類型接口,則能夠額外定義一個異步接口並提供Future類型的方法。
public interface GreetingsService {
String sayHi(String name);
}
@AsyncFor(GreetingsService.class)
public interface GrettingServiceAsync extends GreetingsService {
CompletableFuture<String> sayHiAsync(String name);
}
- 若是你的原始接口定義不是Future類型的返回值,Provider端異步也提供了相似Servlet3.0裏的Async Servlet的編程接口:
RpcContext.startAsync()
public interface AsyncService {
String sayHello(String name);
}
public class AsyncServiceImpl implements AsyncService {
public String sayHello(String name) {
final AsyncContext asyncContext = RpcContext.startAsync();
new Thread(() -> {
asyncContext.write("Hello " + name + ", response from provider.");
}).start();
return null;
}
}
具體的實現原理我在後續文章中結合源碼來說解,注意:這些改動都僅僅支持dubbo協議。
(四)元數據改造
咱們知道2.7之前的版本只有註冊中心,註冊中心的URL有數十個key/value的鍵值對,包含了一個服務全部的元數據。在愈來愈多的功能被增長,元數據也變得異常龐大,就出現了下面的問題:
- 註冊中心存儲的URL過長:這會致使存儲的壓力驟增,數據龐大致使在修改元數據後的通知效率也降低,而且增長了消費者對於元數據解析的壓力,尤爲是在大規模場景下的內存增加顯著
- 註冊中心承擔了過多的服務治理配置的功能:初始配置的同步、存儲各類運行期配置規則加重了註冊中心的壓力,配置規則的靈活性也有所限制,阻礙了市場上的一些優秀微服務配置中心的集成和擴展。
- 屬性的功能定位不清晰:methods,pid,owner雖然是爲了查詢服務而註冊的屬性,可是這些簡陋的信息很難知足查詢服務治理需求,因此須要更加豐富的註冊數據。例如methods,雖然方法列表的內容已經很長,可是在ops開發服務測試/mock功能時,發現須要的方法簽名等數據仍是沒法獲取。
針對以上問題,在2.7中,將URL中的元數據劃分了三個部分:
- 元數據信息:接口的完整定義,包含接口名,接口所含的方法,以及方法所含的出入參信息。對於服務測試和服務mock有很重要做用。
- 執行鏈路上數據:須要將參數從provider端傳遞給consume端,讓consume端感知的到,好比token、timeout等
- 服務本身持有的配置&Ops需求:只有provider端本身須要或者consume端本身須要的數據,好比executes、document等
改造後,分別造成三大中心:
- 註冊中心:理想狀況下,註冊中心將只用於關鍵服務信息(核心鏈路)的同步,進一步減輕註冊中心的存儲壓力,提升地址同步效率,同時緩解當前因爲URL冗餘在大規模推送時形成的Consumer端內存計算壓力。
- 配置中心:解決當前配置和地址信息耦合的問題,經過抽象動態配置層,讓開發者能夠對接微服務場景下更經常使用的、更專業的配置中心,如Nacos, Apollo, Consul, Etcd等;提供更靈活的、更豐富的配置規則,包括服務、應用不一樣粒度的配置,更豐富的路由規則,集中式管理的動態參數規則等
- 服務查詢治理中心:對於純粹的服務查詢相關的數據,包括Consumer的服務訂閱數據,每每都是註冊後不可變的而且不須要節點間的同步,如當前URL能夠看到的methods、owner等key以及全部的Consumer端URL,目前支持 redis(推薦),zookeeper,將做爲Dubbo-Admin支持的服務測試,模擬和其餘服務治理功能的基礎。
(五)服務治理規則加強
路由規則的加強
Dubbo 提供了具備必定擴展性的路由規則,其中具備表明性的是條件路由和腳本路由。2.6.x及如下版本存在的問題:
- 路由規則存儲在註冊中心
- 只支持服務粒度的路由,應用級別沒法定義路由規則
- 支持路由緩存,但基本不具備擴展性
- 一個服務或應用容許定義多條路由規則,服務治理沒法管控
- 實現上,每條規則生成一個Router實例並動態加載
在2.7.x版本中,對路由規則作了加強:
-
豐富的路由規則。
- 條件路由:支持應用程序級別和服務級別條件。
- 標記路由:新引入以更好地支持流量隔離,例如灰色部署
配置中心對服務治理的加成
- 將治理規則與註冊表分離,也就是出現了配置中心,使配置中心更容易擴展。有Apollo和Zookeeper,2.7.1還支持了consul和etcd。
- 應用程序級動態配置支持。
- 使用YAML做爲配置語言,更易於閱讀和使用
(六)新增配置中心
配置中心(v2.7.0)在Dubbo中承擔兩個職責:
- 外部化配置:啓動配置的集中式存儲 (簡單理解爲dubbo.properties的外部化存儲)外部化配置目的之一是實現配置的集中式管理,這部分業界已經有不少成熟的專業配置系統如Apollo, Nacos等,Dubbo所作的主要是保證能配合這些系統正常工做。外部化配置和其餘本地配置在內容和格式上並沒有區別,能夠簡單理解爲
dubbo.properties
的外部化存儲,配置中心更適合將一些公共配置如註冊中心、元數據中心配置等抽取以便作集中管理
- 服務治理:服務治理規則的存儲與通知。
配置的操做能夠查看官方文檔,因爲如今dubbo支持多種配置方式,因此這裏須要強調的是配置覆蓋的優先級,從上至下優先級依此下降:
(七)序列化擴展
新增了Protobuf序列化支持。
(八)其餘
其餘的bug修復以及一些小細節優化請查看github上的Issues或者PR。
後記
升級2.7.0的引導請查看如下連接:
http://dubbo.apache.org/zh-cn...
該文章講解了dubbo2.7的新特性,如今2.7.1已經發布,有興趣的能夠去看看2.7.1新增了什麼。下一篇我就先從源碼的角度來說講這個異步化的改造。