Springboot整合Dubbo啟動解析Bean定義
根據springboot啟動原理,會先把啟動類下的所有類先進行解析bean定義,所以要先EnableDubbo這個注解,再根據這個注解里面的注解,可以知道import的兩個類DubboComponentScanRegistrar和DubboConfigConfigurationSelector
DubboConfigConfigurationSelector看上去主要用來加載dubbo配置的一些信息
DubboAutoConfiguration這個類是在自動裝配是加載的
本地的類定義和spring.factories需要的類定義加載完會調用this.reader.loadBeanDefinitions(configClasses);開始對ImportBeanDefinitionRegistrar注解的類進行bean定義注冊,DubboComponentScanRegistrar做了兩件事,注冊了ServiceAnnotationBeanPostProcessor和ReferenceAnnotationBeanPostProcessor的bean定義
然后在ServiceAnnotationBeanPostProcessor掃描出有dubbo的@Service注解的類進行注冊,這里會新增一個bean定義類ServiceBean:userServiceIml:xx.xx.comsumer.service.UserService,這個類的class是ServiceBean,以此類推會把所有的@com.alibaba.dubbo.config.annotation.Service注解的都解析了
ReferenceAnnotationBeanPostProcessor主要是對@Reference注解的類做動態代理
Service暴露
等springboot創建完所有bean,由于ServiceBean實現了ApplicationListener接口,所以在ServiceBean的類一些bean創建完之后,會調用onApplicationEvent這個方法,這個方法就是對服務的暴露
給provider,module,registries,monitor,protocols填充屬性
JavassistProxyFactory做動態代理
InjvmProtocol導出
然后就是遠程導出
導出服務
到這里就是創建完netty了,就是獲取注冊中心注冊數據
整個過程差不多就是這樣
Reference服務發現
由于ReferenceBean實現了FactoryBean,所以在創建bean的時候會調用getObject方法
消費者調用提供者服務
Dubbo總結
dubbo協議
支持多協議,默認dubbo協議還有rmi,hessian,http,webservice,hrift,memcached,redis,rest等協議
注冊中心
支持多注冊中心,默認使用 Zookeeper 作為注冊中心,還有 Redis、Multicast、Simple 注冊中心,但不推薦。dubbo會把數據存到本地,所以注冊中心掛了,消費者也可以調用提供者
負載均衡
隨機,輪訓,活躍度,一致性hash
Dubbo容錯策略
failover cluster模式
provider 宕機重試以后,請求會分到其他的provider上,默認兩次,可以手動設置重試次數,建議把寫操作重試次數設置成0。
failback模式
失敗自動恢復會在調用失敗后,返回一個空結果給服務消費者。并通過定時任務對失敗的調用進行重試,適合執行消息通知等操作。
failfast cluster模式
快速失敗只會進行一次調用,失敗后立即拋出異常。適用于冪等操作,寫操作,類似于failover cluster模式中重試次數設置為0的情況。
failsafe cluster模式
失敗安全是指,當調用過程中出現異常時,僅會打印異常,而不會拋出異常。適用于寫入審計日志等操作。
forking cluster模式
并行調用多個服務器,只要一個成功即返回。通常用于實時性要求較高的讀操作,但需要浪費更多服務資源。可通過 forks=“2” 來設置最大并行數。
broadcacst cluster模式
廣播調用所有提供者,逐個調用,任意一臺報錯則報錯。通常用于通知所有提供者更新緩存或日志等本地資源信息。
序列化
dubbo序列化:阿里尚未開發成熟的高效java序列化實現,阿里不建議在生產環境使用它
hessian2序列化(默認推薦):hessian是一種跨語言的高效二進制序列化方式。但這里實際不是原生的hessian2序列化,而是阿里修改過的hessian lite,它是dubbo RPC默認啟用的序列化方式
json序列化:目前有兩種實現,一種是采用的阿里的fastjson庫,另一種是采用dubbo中自己實現的簡單json庫,但其實現都不是特別成熟,而且json這種文本序列化性能一般不如上面兩種二進制序列化。
java序列化:主要是采用JDK自帶的Java序列化實現,性能很不理想。
整體設計
圖例說明:
- 圖中左邊淡藍背景的為服務消費方使用的接口,右邊淡綠色背景的為服務提供方使用的接口,位于中軸線上的為雙方都用到的接口。
- 圖中從下至上分為十層,各層均為單向依賴,右邊的黑色箭頭代表層之間的依賴關系,每一層都可以剝離上層被復用,其中,Service 和 Config 層為 API,其它各層均為 SPI。
- 圖中綠色小塊的為擴展接口,藍色小塊為實現類,圖中只顯示用于關聯各層的實現類。
- 圖中藍色虛線為初始化過程,即啟動時組裝鏈,紅色實線為方法調用過程,即運行時調用鏈,紫色三角箭頭為繼承,可以把子類看作父類的同一個節點,線上的文字為調用的方法。
各層說明
- Config 配置層:對外配置接口,以 ServiceConfig, ReferenceConfig 為中心,可以直接初始化配置類,也可以通過 spring 解析配置生成配置類
- Proxy 服務代理層:服務接口透明代理,生成服務的客戶端 Stub 和服務器端 Skeleton, 以 ServiceProxy 為中心,擴展接口為 ProxyFactory
- Registry 注冊中心層:封裝服務地址的注冊與發現,以服務 URL 為中心,擴展接口為 RegistryFactory, Registry, RegistryService
- Cluster 路由層:封裝多個提供者的路由及負載均衡,并橋接注冊中心,以 Invoker 為中心,擴展接口為 Cluster, Directory, Router, LoadBalance
- Monitor 監控層:RPC 調用次數和調用時間監控,以 Statistics 為中心,擴展接口為 MonitorFactory, Monitor, MonitorService
- Protocol 遠程調用層:封裝 RPC 調用,以 Invocation, Result 為中心,擴展接口為 Protocol, Invoker, Exporter
- Exchange 信息交換層:封裝請求響應模式,同步轉異步,以 Request, Response 為中心,擴展接口為 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer
- Transport 網絡傳輸層:抽象 mina 和 netty 為統一接口,以 Message 為中心,擴展接口為 Channel, Transporter, Client, Server, Codec
- Serialize 數據序列化層:可復用的一些工具,擴展接口為 Serialization, ObjectInput, ObjectOutput, ThreadPool
Zookeeper和Dubbo的關系
在 Provider 上可以配置的 Consumer 端的屬性有哪些
1)timeout:方法調用超時
2)retries:失敗重試次數,默認重試 2 次
3)loadbalance:負載均衡算法,默認隨機
4)actives 消費者端,最大并發調用限制
Dubbo啟動時如果依賴的服務不可用會怎樣
Dubbo 缺省會在啟動時檢查依賴的服務是否可用,不可用時會拋出異常,阻止 Spring 初始化完成,默認 check="true",可以通過 check="false" 關閉檢查。
當一個服務接口有多種實現時怎么做
當一個接口有多種實現時,可以用 group 屬性來分組,服務提供方和消費方都指定同一個 group 即可。
服務上線怎么兼容舊版本
可以用版本號(version)過渡,多個不同版本的服務注冊到注冊中心,版本號不同的服務相互間不引用。這個和服務分組的概念有一點類似。
Dubbo可以對結果進行緩存嗎
可以,Dubbo 提供了聲明式緩存,用于加速熱門數據的訪問速度,以減少用戶加緩存的工作量。
Dubbo服務之間的調用是阻塞的嗎
默認是同步等待結果阻塞的,支持異步調用。
Dubbo 是基于 NIO 的非阻塞實現并行調用,客戶端不需要啟動多線程即可完成并行調用多個遠程服務,相對多線程開銷較小,異步調用會返回一個 Future 對象。
異步調用流程圖如下。