你們好,今天開始給你們分享 — Dubbo 專題之 Dubbo 延遲服務暴露。在前一個章節中咱們介紹了 Dubbo Stub
和 Mock
,咱們例舉了常見的使用場景而且進行了源碼解析來分析其實現原理,同時咱們知道 Dubbo Stub
和 Mock
都是基於對調用代理對象的包裝實現的,這樣能夠爲咱們在調用服務時作一些前置或後置處理工做。有的小夥伴可能會遇到這樣的場景:在咱們的應用服務中有不少的本地緩存或者分佈式緩存,這些緩存有可能須要加載一段時間那麼在這個緩存加載過程當中咱們但願接口不要對外提供服務,那有沒有一種機制讓咱們對緩存加載完成後再暴露服務的機制呢?那麼在本章節咱們會經過介紹 Dubbo 延遲暴露服務來解決這個問題。那什麼是延遲服務暴露?以及延遲服務暴露的實現原理是什麼呢?下面就讓咱們快速開始吧!java
在當前咱們使用的Dubbo2.7.x
版本中服務暴露時機是 Spring
容器啓動完成並廣播出事件 ApplicationContextEvent
時才進行對服務暴露。那這裏所謂的延遲暴露也就是在接收到 ApplicationContextEvent
事件後開始一個指定時間的延遲直到延遲時間到纔開始對服務進行暴露。延遲服務暴露的核心就是一個延遲調度器,當延遲時間到就開始進行服務暴露。其配置參數爲:delay="5000"
,這裏的時間單位爲毫秒。git
Tips:其餘的 Dubbo 版本的服務暴露可能有一些出入,讀者以最新版本爲主。
延遲服務暴露能夠經過 XML 或者註解的方式進行配置且指定的延遲時間單位爲毫秒。spring
<!--延遲1秒暴露Dubbo服務--> <dubbo:service interface="com.muke.dubbocourse.protocol.api.BookFacade" ref="bookFacade" delay="1000" />
若是配置delay="-1"
則表示在 Spring
容器初始化完後再暴露服務。數據庫
@DubboService(delay = 1000) public class BookFacadeImpl implements BookFacade { }
使用@DubboService
註解或@Service
註解。delay = 1000
表示延遲1秒後才進行服務暴露。apache
經過上面的延遲服務暴露的簡介咱們能夠了解到:延遲服務暴露其實就是針對須要暴露的服務配置一個固定的延遲時間,延遲時間一到當即開始服務的暴露。那麼咱們基於上面的服務暴露的時效性咱們簡單的介紹一些工做中常使用的場景:編程
咱們一樣以獲取圖書列表爲例來進行演示。項目結構以下:bootstrap
由於延遲服務暴露是配置服務提供端,全部咱們這裏只看服務提供者的 XML 配置dubbo-provider-xml.xml
:api
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <dubbo:application name="demo-provider" metadata-type="remote"/> <!--註冊中心--> <dubbo:registry address="zookeeper://127.0.0.1:2181"/> <bean id="bookFacade" class="com.muke.dubbocourse.delayexport.provider.BookFacadeImpl"/> <!--延遲1秒暴露Dubbo服務--> <dubbo:service interface="com.muke.dubbocourse.common.api.BookFacade" ref="bookFacade" delay="1000"/> </beans>
上面的 XML 配置中主要配置了delay="1000"
表示等 Spring
容器啓動完成後服務延遲1
秒鐘後纔開始暴露服務。其註解配置也是相似就再也不演示。緩存
下面咱們簡單的經過服務暴露的源碼進行分析。咱們都知道當 Spring 容器啓動完成會發出 ApplicationContextEvent
事件,咱們能夠看到這個`org.apache.dubbo.config.spring.context
.DubboBootstrapApplicationListener#
onApplicationContextEvent`方法核心代碼:微信
public void onApplicationContextEvent(ApplicationContextEvent event) { if (event instanceof ContextRefreshedEvent) { //Spring 容器啓動完成 onContextRefreshedEvent((ContextRefreshedEvent) event); } else if (event instanceof ContextClosedEvent) { //Spring 容器關閉 onContextClosedEvent((ContextClosedEvent) event); } }
當接收到ContextRefreshedEvent
事件後會最終會調用`org.apache.dubbo.config.bootstrap.
DubboBootstrap#start`方法啓動服務註冊核心代碼以下:
public DubboBootstrap start() { //判斷服務是否啓動 防止重複暴露服務 注意:這裏是原子操做 if (started.compareAndSet(false, true)) { initialize(); //.. // 暴露Dubbo服務 exportServices(); //... } return this; }
上面的代碼先進行原子操做去設置啓動標識防止重複暴露服務,其exportServices
代碼以下:
/*** * * dubbo服務導出 * * @author liyong * @date 16:23 2020-03-01 * @param * @exception * @return void **/ private void exportServices() { //循環全部須要服務暴露的配置 configManager.getServices().forEach(sc -> { // TODO, compatible with ServiceConfig.export() ServiceConfig serviceConfig = (ServiceConfig) sc; serviceConfig.setBootstrap(this); //是否異步導出 if (exportAsync) { //獲取線程池 ExecutorService executor = executorRepository.getServiceExporterExecutor(); Future<?> future = executor.submit(() -> { //異步服務暴露 sc.export(); }); asyncExportingFutures.add(future); } else { //同步服務暴露導出 sc.export(); exportedServices.add(sc); } }); }
上面的代碼是循環對全部的 Dubbo 服務進行暴露,注意這裏有一個exportAsync
標識來判斷是否異步暴露服務(異步暴露服務是指在另外的線程執行不阻塞當前線程)。下面咱們看到主要的服務暴露代碼org.apache.dubbo.config.ServiceConfig#export
方法:
/** * * 服務暴露 * * @author liyong * @date 10:55 PM 2020/11/18 * @param * @exception * @return void **/ public synchronized void export() { //... //是否延遲暴露判斷 if (shouldDelay()) { //延遲暴露 DELAY_EXPORT_EXECUTOR.schedule(this::doExport, getDelay(), TimeUnit.MILLISECONDS); } else { //服務暴露 doExport(); } }
上面便是咱們延遲服務暴露的核心代碼 DELAY_EXPORT_EXECUTOR.schedule(this::doExport, getDelay(), TimeUnit.MILLISECONDS)
使用延時調度器進行服務暴露。
在本小節中咱們主要學習了 Dubbo 中延遲服務暴露以及使用方式,同時也分析了延遲服務暴露實現的原理,其本質上是經過延遲調度器進行服務暴露,其中延遲調度器是關鍵所在。
本節課程的重點以下:
我的從事金融行業,就任過易極付、思建科技、某網約車平臺等重慶一流技術團隊,目前就任於某銀行負責統一支付系統建設。自身對金融行業有強烈的愛好。同時也實踐大數據、數據存儲、自動化集成和部署、分佈式微服務、響應式編程、人工智能等領域。同時也熱衷於技術分享創立公衆號和博客站點對知識體系進行分享。關注公衆號: 青年IT男 獲取最新技術文章推送!
博客地址: http://youngitman.tech
微信公衆號: