Spring Eureka 從開源轉變爲閉源,Consul 正在崛起,而 Dubbo 又開始從新更新。目前市場上仍有很多公司使用dubbo咱們也須要繼續學習。java
隨着服務化的進一步發展,服務愈來愈多,服務之間的調用和依賴關係也愈來愈複雜,誕生了面向服務的架構體系(SOA),git
也所以衍生出了一系列相應的技術,如對服務提供、服務調用、鏈接處理、通訊協議、序列化方式、服務發現、服務路由、日誌輸出等行爲進行封裝的服務框架。github
就這樣爲分佈式系統的服務治理框架就出現了,Dubbo也就這樣產生了。web
接口服務層(Service):該層與業務邏輯相關,根據 provider 和 consumer 的業務設計對應的接口和實現redis
配置層(Config):對外配置接口,以 ServiceConfig 和 ReferenceConfig 爲中心spring
服務代理層(Proxy):服務接口透明代理,生成服務的客戶端 Stub 和 服務端的 Skeleton,以 ServiceProxy 爲中心,擴展接口爲 ProxyFactory設計模式
服務註冊層(Registry):封裝服務地址的註冊和發現,以服務 URL 爲中心,擴展接口爲 RegistryFactory、Registry、RegistryService緩存
路由層(Cluster):封裝多個提供者的路由和負載均衡,並橋接註冊中心,以Invoker 爲中心,擴展接口爲 Cluster、Directory、Router和LoadBlancce安全
監控層(Monitor):RPC調用次數和調用時間監控,以 Statistics 爲中心,擴展接口爲 MonitorFactory、Monitor和MonitorService 服務器
遠程調用層(Protocal):封裝 RPC 調用,以 Invocation 和 Result 爲中心,擴展接口爲 Protocal、Invoker和Exporter
信息交換層(Exchange):封裝請求響應模式,同步轉異步。以 Request 和 Response 爲中心,擴展接口爲 Exchanger、ExchangeChannel、ExchangeClient和ExchangeServer
網絡傳輸層(Transport):抽象 mina 和 netty 爲統一接口,以 Message 爲中心,擴展接口爲Channel、Transporter、Client、Server和Codec
數據序列化層(Serialize):可複用的一些工具,擴展接口爲Serialization、 ObjectInput、ObjectOutput和ThreadPool
默認也推薦使用netty框架,還有mina。
默認是阻塞的,能夠異步調用,沒有返回值的能夠這麼作。
Dubbo 是基於 NIO 的非阻塞實現並行調用,客戶端不須要啓動多線程便可完成並行調用多個遠程服務,相對多線程開銷較小,異步調用會返回一個 Future 對象。
推薦使用 Zookeeper 做爲註冊中心,還有 Redis、Multicast、Simple 註冊中心,但不推薦。
推薦使用Hessian序列化,還有Duddo、FastJson、Java自帶序列化。
服務失效踢出基於zookeeper的臨時節點原理。
採用多版本開發,不影響舊版本。
能夠結合zipkin實現分佈式服務追蹤。
配置 | 配置說明 |
---|---|
dubbo:service | 服務配置 |
dubbo:reference | 引用配置 |
dubbo:protocol | 協議配置 |
dubbo:application | 應用配置 |
dubbo:module | 模塊配置 |
dubbo:registry | 註冊中心配置 |
dubbo:monitor | 監控中心配置 |
dubbo:provider | 提供方配置 |
dubbo:consumer | 消費方配置 |
dubbo:method | 方法配置 |
dubbo:argument | 參數配置 |
能夠點對點直連,修改配置便可,也能夠經過telnet直接某個服務。
集羣容錯方案 | 說明 |
---|---|
Failover Cluster | 失敗自動切換,自動重試其它服務器(默認) |
Failfast Cluster | 快速失敗,當即報錯,只發起一次調用 |
Failsafe Cluster | 失敗安全,出現異常時,直接忽略 |
Failback Cluster | 失敗自動恢復,記錄失敗請求,定時重發 |
Forking Cluster | 並行調用多個服務器,只要一個成功即返回 |
Broadcast Cluster | 廣播逐個調用全部提供者,任意一個報錯則報錯 |
能夠經過dubbo:reference 中設置 mock="return null"。mock 的值也能夠修改成 true,而後再跟接口同一個路徑下實現一個 Mock 類,命名規則是 「接口名稱+Mock」 後綴。而後在 Mock 類裏實現本身的降級邏輯
在註冊中心找不到對應的服務,檢查service實現類是否添加了@service註解
沒法鏈接到註冊中心,檢查配置文件中的對應的測試ip是否正確
Consumer端在發起調用以前會先走filter鏈;provider端在接收到請求時也是先走filter鏈,而後才進行真正的業務邏輯處理。
默認狀況下,在consumer和provider的filter鏈中都會有Monitorfilter。
一、MonitorFilter向DubboMonitor發送數據
二、DubboMonitor將數據進行聚合後(默認聚合1min中的統計數據)暫存到ConcurrentMap<Statistics, AtomicReference> statisticsMap,而後使用一個含有3個線程(線程名字:DubboMonitorSendTimer)的線程池每隔1min鍾,調用SimpleMonitorService遍歷發送statisticsMap中的統計數據,每發送完畢一個,就重置當前的Statistics的AtomicReference
三、SimpleMonitorService將這些聚合數據塞入BlockingQueue queue中(隊列大寫爲100000)
四、SimpleMonitorService使用一個後臺線程(線程名爲:DubboMonitorAsyncWriteLogThread)將queue中的數據寫入文件(該線程以死循環的形式來寫)
五、SimpleMonitorService還會使用一個含有1個線程(線程名字:DubboMonitorTimer)的線程池每隔5min鍾,將文件中的統計數據畫成圖表
Dubbo框架在初始化和通訊過程當中使用了多種設計模式,可靈活控制類加載、權限控制等功能。
工廠模式
Provider在export服務時,會調用ServiceConfig的export方法。ServiceConfig中有個字段:
private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
Dubbo裏有不少這種代碼。這也是一種工廠模式,只是實現類的獲取採用了JDK SPI的機制。這麼實現的優勢是可擴展性強,想要擴展實現,只須要在classpath下增長個文件就能夠了,代碼零侵入。另外,像上面的Adaptive實現,能夠作到調用時動態決定調用哪一個實現,可是因爲這種實現採用了動態代理,會形成代碼調試比較麻煩,須要分析出實際調用的實現類。
裝飾器模式
Dubbo在啓動和調用階段都大量使用了裝飾器模式。以Provider提供的調用鏈爲例,具體的調用鏈代碼是在ProtocolFilterWrapper的buildInvokerChain完成的,具體是將註解中含有group=provider的Filter實現,按照order排序,最後的調用順序是:
EchoFilter -> ClassLoaderFilter -> GenericFilter -> ContextFilter -> ExecuteLimitFilter -> TraceFilter -> TimeoutFilter -> MonitorFilter -> ExceptionFilter
更確切地說,這裏是裝飾器和責任鏈模式的混合使用。例如,EchoFilter的做用是判斷是不是回聲測試請求,是的話直接返回內容,這是一種責任鏈的體現。而像ClassLoaderFilter則只是在主功能上添加了功能,更改當前線程的ClassLoader,這是典型的裝飾器模式。
觀察者模式
Dubbo的Provider啓動時,須要與註冊中心交互,先註冊本身的服務,再訂閱本身的服務,訂閱時,採用了觀察者模式,開啓一個listener。註冊中心會每5秒定時檢查是否有服務更新,若是有更新,向該服務的提供者發送一個notify消息,provider接受到notify消息後,即運行NotifyListener的notify方法,執行監聽器方法。
動態代理模式
Dubbo擴展JDK SPI的類ExtensionLoader的Adaptive實現是典型的動態代理實現。Dubbo須要靈活地控制實現類,即在調用階段動態地根據參數決定調用哪一個實現類,因此採用先生成代理類的方法,可以作到靈活的調用。生成代理類的代碼是ExtensionLoader的createAdaptiveExtensionClassCode方法。代理類的主要邏輯是,獲取URL參數中指定參數的值做爲獲取實現類的key。
Spring容器在啓動的時候,會讀取到Spring默認的一些schema以及Dubbo自定義的schema,每一個schema都會對應一個本身的NamespaceHandler,NamespaceHandler裏面經過BeanDefinitionParser來解析配置信息並轉化爲須要加載的bean對象!
JDK SPI
JDK 標準的 SPI 會一次性加載全部的擴展實現,若是有的擴展吃實話很耗時,但也沒用上,很浪費資源。
因此只但願加載某個的實現,就不現實了
DUBBO SPI
1,對Dubbo進行擴展,不須要改動Dubbo的源碼
2,延遲加載,能夠一次只加載本身想要加載的擴展實現。
3,增長了對擴展點 IOC 和 AOP 的支持,一個擴展點能夠直接 setter 注入其它擴展點。
3,Dubbo的擴展機制能很好的支持第三方IoC容器,默認支持Spring Bean。
目前暫時不支持,可與經過 tcc-transaction框架實現
介紹:tcc-transaction是開源的TCC補償性分佈式事務框架
Git地址:https://github.com/changmingx...
TCC-Transaction 經過 Dubbo 隱式傳參的功能,避免本身對業務代碼的入侵。
爲了提升數據訪問的速度。Dubbo提供了聲明式緩存,以減小用戶加緩存的工做量
<dubbo:reference cache="true" />
其實比普通的配置文件就多了一個標籤 cache="true"
能夠用版本號(version)過渡,多個不一樣版本的服務註冊到註冊中心,版本號不一樣的服務相互間不引用。這個和服務分組的概念有一點相似。
Dubbo 必須依賴 JDK,其餘爲可選。
dubbo服務發佈以後,咱們能夠利用telnet命令進行調試、管理。
Dubbo2.0.5以上版本服務提供端口支持telnet命令
鏈接服務
telnet localhost 20880 //鍵入回車進入Dubbo命令模式。
查看服務列表
dubbo>ls com.test.TestService dubbo>ls com.test.TestService create delete query
以經過dubbo:reference 中設置 mock="return null"。mock 的值也能夠修改成 true,而後再跟接口同一個路徑下實現一個 Mock 類,命名規則是 「接口名稱+Mock」 後綴。而後在 Mock 類裏實現本身的降級邏輯
Dubbo 是經過 JDK 的 ShutdownHook 來完成優雅停機的,因此若是使用 kill -9 PID 等強制關閉指令,是不會執行優雅停機的,只有經過 kill PID 時,纔會執行。
Dubbox 是繼 Dubbo 中止維護後,噹噹網基於 Dubbo 作的一個擴展項目,如加了服務可 Restful 調用,更新了開源組件等。
根據微服務架構在各方面的要素,看看Spring Cloud和Dubbo都提供了哪些支持。
Dubbo | Spring Cloud | |
---|---|---|
服務註冊中心 | Zookeeper | Spring Cloud Netflix Eureka |
服務調用方式 | RPC | REST API |
服務網關 | 無 | Spring Cloud Netflix Zuul |
斷路器 | 不完善 | Spring Cloud Netflix Hystrix |
分佈式配置 | 無 | Spring Cloud Config |
服務跟蹤 | 無 | Spring Cloud Sleuth |
消息總線 | 無 | Spring Cloud Bus |
數據流 | 無 | Spring Cloud Stream |
批量任務 | 無 | Spring Cloud Task |
使用Dubbo構建的微服務架構就像組裝電腦,各環節咱們的選擇自由度很高,可是最終結果頗有可能由於一條內存質量不行就點不亮了,老是讓人不怎麼放心,可是若是你是一名高手,那這些都不是問題;而Spring Cloud就像品牌機,在Spring Source的整合下,作了大量的兼容性測試,保證了機器擁有更高的穩定性,可是若是要在使用非原裝組件外的東西,就須要對其基礎有足夠的瞭解。
別的還有spring的spring cloud,facebook的thrift,twitter的finagle等