dubbo分析
dubbo為什麼要對接spring,如何無縫對接
原因比較簡單,首先就是spring在開發環境的成熟以及使用的易用都是好評,spring本身的擴充套件成本也不高
關於xsd:schema的各個屬性具體含義就不作過多陳述,大家可以參見
http://www.w3school.com.cn/sc…
DubboBeanDefinitionParser和DubboNamespaceHandler的完成了對schemas的實現。原始碼暫且另說,
dubbo為什麼擴充套件性好,是如何實現的?
ExtensionLoader dubbo核心類。
dubbo擴充套件性好主要在於它的外掛形式,針對業務什麼技術好就用什麼(只針對在rpc架構的要點方面)
通過外掛機制解耦依賴來實現框架設計原則中的針對介面程式設計而不針對實現。 如果屬性ExtensionLoader就屬性了dubbo的擴充套件。
提到擴充套件,我們看看jdk的service provider interface,後文用SPI簡寫,主要解耦機制比較強勢體現。經常看原始碼的同學應該很熟了吧,於dubbo的SPI對比。
jdk-spi:當服務的提供者,提供了服務介面的一種實現之後,在jar包的META-INF/services/目錄裡同時建立一個以服務介面命名的檔案。該檔案裡就是實現該服務介面的具體實現類。而當外部程式裝配這個模組的時候,就能通過該jar包META-INF/services/裡的配置檔案找到具體的實現類名,並裝載例項化,完成模組的注入。
各種jdbc驅動,log4j,spring對servlet3.0規範對ServletContainerInitializer的實現等。JDK的SPI是載入所有的實現,這裡好像又得說到類載入器,可以自己去看看相關的文章。而dubbo只載入自己所想要的。
dubbo的SPI是對jdk的封裝,來滿足自己的特性。
dubbo-spi:dubbo的載入是單例模式,可以延遲載入
ExtensionLoader
| +-getAdativeExtension #獲取擴充套件的介面卡類#
| +-createAdativeExtension #快取中沒有就建立一個#
| +-getAdativeExtensionClasses #獲取介面卡類#
| +-getExtensionClass #載入所有擴充套件點實現類#
| -createAdativeExtansionClass #dubbo幫我們動態建立一個介面卡類
大致的流程如此,原始碼暫時先不詳解了。
簡而言之,dubbo的特性
dubbo 的動態代理
dubbo自己實現了一套代理機制
/*com.alibaba.dubbo.common.bytecode.Proxy*/
public abstract class Proxy
{
private static final AtomicLong PROXY_CLASS_COUNTER = new AtomicLong(0);
private static final String PACKAGE_NAME = Proxy.class.getPackage().getName();
public static final InvocationHandler RETURN_NULL_INVOKER = new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args){ return null; }
};
public static final InvocationHandler THROW_UNSUPPORTED_INVOKER = new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args){ throw new UnsupportedOperationException("Method [" + ReflectUtils.getName(method) + "] unimplemented."); }
};
private static final Map<ClassLoader, Map<String, Object>> ProxyCacheMap = new WeakHashMap<ClassLoader, Map<String, Object>>();
private static final Object PendingGenerationMarker = new Object();
根據申明的這些final static物件我們可以大概知道dubbo自己的需求
快取機制: 遍歷所有入參介面+”;”作為Key
/**
* get method desc.
* int do(int arg1) => "do(I)I"
* void do(String arg1,boolean arg2) => "do(Ljava/lang/String;Z)V"
* /
版本機制: 通過 PROXY_CLASS_COUNTER 作為單個版本號,規則大概為 pkg + “.poxy”+id,保證了沒有衝突
// create ProxyInstance class.
String pcn = pkg + ".proxy" + id;
ccp.setClassName(pcn);
ccp.addField("public static java.lang.reflect.Method[] methods;");
ccp.addField("private " + InvocationHandler.class.getName() + " handler;");
ccp.addConstructor(Modifier.PUBLIC, new Class<?>[]{ InvocationHandler.class }, new Class<?>[0], "handler=$1;");
ccp.addDefaultConstructor();
Class<?> clazz = ccp.toClass();
clazz.getField("methods").set(null, methods.toArray(new Method[0]));
// create Proxy class.
String fcn = Proxy.class.getName() + id;
ccm = ClassGenerator.newInstance(cl);
ccm.setClassName(fcn);
ccm.addDefaultConstructor();
ccm.setSuperClass(Proxy.class);
ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }");
Class<?> pc = ccm.toClass();
proxy = (Proxy)pc.newInstance();
dubbo的新版維護
2.5.4 解決問題和新功能
優雅的關機
MonitorFilter阻止RPC程式
動態配置:不能指定消費者IP,提供者端的配置不能被刪除。
路由規則解析問題
非同步會影響下游的RPC呼叫。
供應商方面的流量控制優化。
社群報告的一些錯誤修正。
2.5.6解決問題和新功能
修復了PojoUtils問題:列舉型別,私有檔案。
當提供程式執行緒池耗盡時,RejectException不能傳送到使用者端。
當負載過載時避免不必要的響應傳輸。
Slf4jLogger可以反映實際的行號。
使用延遲匯出時,併發會導致意外的多埠繫結
當沒有提供者時,模擬不會工作。
一些優化:OverrideListener,在提供程式上停止不必要的心跳,Main Bootstrap程式等。
一些錯誤修正:動態配置不能刪除,telnet invoke支援json引數,監控統計問題等
新功能
支援Netty4 手冊
執行緒池耗盡時自動堆疊轉儲。手冊
Jdk 1.8新的日期時間型別支援hessian2序列化。
2.5.7解決問題和新功能
全新的註釋配置實現,修復了舊註釋版本報告的所有缺陷。(dubbo-spring-boot-starter將在稍後釋出)
*更多詳情請參閱Dubbo Annotation-Driven
支援讀取IP和埠以註冊和繫結環境變數。
例
調整一些XML配置專案:dump.directory等。
Bootstrap在登錄檔無法連線時被阻止。
MonitorService在第一次呼叫MonitorService時無法連線ZK時阻止RPC程式。
標記內部的JSON序列化已棄用,請改用fastjson。
RMI協議支援附件傳遞。
EnumSet型別支援hessian2序列化。
修復了一些錯誤和優化。
2.5.8解決問題和新功能
Dubbo程式設計模型增強。
修復了2.5.7中報告的一些錯誤。
更多細節請參閱Dubbo註解驅動
外部配置EnableDubbo,EnableDubboBindings也為Spring-Boot-Starter做準備。
更多細節請參閱Dubbo外部化配置
通過telnet和更強大的OPShttp:僅支援online,offline在此版本中,將在以下版本中提供更多功能
路由規則不應該每次都預設執行
優化春季活動表現
修復了使用策展人時的NPE路徑問題
修復了使用dubbo-admin報告的一些錯誤
Redis登錄檔支援認證
2.5.9解決問題和新功能
bug
向後相容RMI協議
Hessian序列化:
為java.util.Time型別新增空檢查
恢復hessian的覆蓋序列,子類的欄位應該覆蓋父類的欄位,而不是其他方式
Redis和多播登錄檔不能離線。
增加功能
註釋增強。基於這個版本的dubbo-spring-boot-starter也已經發布。
為qos新增開關:dubbo.application.qos.enable=true/false。例如,注意我們配置qos的新方法,dubbo.qos.port已被更改為dubbo.application.qos.port。
正常關機,在登錄檔取消註冊和執行緒池關閉之間增加額外的等待時間。
通過避免使用低效率來提高黑森序列化的效能synchronized。
引數驗證失敗時避免重試。
條件路由器還應檢查預設值。
解決漏洞
在這個版本中,我們將檢查從網路接收到的序列化標識(只有當標識JDK序列化時)與當前例項中的標識匹配。如果無法匹配,則反序列化過程將被拒絕。由於原來的JDK反序列化有安全問題,我們這樣做是為了防止序列化型別,例如從意外篡改hessian2來java。
2.5.10解決問題和新功能
bug
FutureUnapter中的TimeUnit轉換錯誤。
在Docker中部署時,提供者端無法呼叫服務
Hessian序列化問題型別:short和byte。
刪除isdestrory()在登錄檔中檢查,確保在關閉時取消註冊
引用註釋支援註釋型別上的註釋
2.6.0解決問題和新功能
在本次釋出中,我們主要合併了當當網貢獻的dubbox分支,突出了以下功能:
REST支援(通過整合resteasy)
高效能的序列化框架:kryo,FST
嵌入式tomcat支援
我們試圖保留原來的分支,同時進行以下小調整:
升級了一些依賴的版本:kryo,FST和tomcat
刪除了對核心RPC協議的更改以避免相容性問題