前言

大家好,明天开始给大家分享 — Dubbo 专题之 Dubbo 提早服务裸露。在前一个章节中咱们介绍了 Dubbo StubMock,咱们例举了常见的应用场景并且进行了源码解析来剖析其实现原理,同时咱们晓得 Dubbo StubMock 都是基于对调用代理对象的包装实现的,这样能够为咱们在调用服务时做一些前置或后置解决工作。有的小伙伴可能会遇到这样的场景:在咱们的应用服务中有很多的本地缓存或者分布式缓存,这些缓存有可能须要加载一段时间那么在这个缓存加载过程中咱们心愿接口不要对外提供服务,那有没有一种机制让咱们对缓存加载实现后再裸露服务的机制呢?那么在本章节咱们会通过介绍 Dubbo 提早裸露服务来解决这个问题。那什么是提早服务裸露?以及提早服务裸露的实现原理是什么呢?上面就让咱们疾速开始吧!

1. 提早服务裸露简介

在以后咱们应用的Dubbo2.7.x版本中服务裸露机会是 Spring 容器启动实现并播送出事件 ApplicationContextEvent 时才进行对服务裸露。那这里所谓的提早裸露也就是在接管到 ApplicationContextEvent 事件后开始一个指定工夫的提早直到延迟时间到才开始对服务进行裸露。提早服务裸露的外围就是一个提早调度器,当延迟时间到就开始进行服务裸露。其配置参数为:delay="5000",这里的工夫单位为毫秒。

Tips:其余的 Dubbo 版本的服务裸露可能有一些出入,读者以最新版本为主。

2. 应用形式

提早服务裸露能够通过 XML 或者注解的形式进行配置且指定的延迟时间单位为毫秒。

2.1 XML 配置形式

    <!--提早1秒裸露Dubbo服务-->    <dubbo:service interface="com.muke.dubbocourse.protocol.api.BookFacade" ref="bookFacade" delay="1000" />

如果配置delay="-1"则示意在 Spring 容器初始化完后再裸露服务。

2.2 注解配置形式

@DubboService(delay = 1000)public class BookFacadeImpl implements BookFacade {}

应用@DubboService注解或@Service注解。delay = 1000示意提早1秒后才进行服务裸露。

3. 应用场景

通过下面的提早服务裸露的简介咱们能够理解到:提早服务裸露其实就是针对须要裸露的服务配置一个固定的延迟时间,延迟时间一到立刻开始服务的裸露。那么咱们基于下面的服务裸露的时效性咱们简略的介绍一些工作中常应用的场景:

  1. 缓存预热:当咱们的裸露服务须要依赖一些静态数据,这些静态数据是通过加载数据库或者文件而后缓存到利用内存中。此时咱们能够通过在服务提早裸露的时间段内进行缓存预加载。
  2. 依赖资源:假如咱们对外提供的服务须要依赖另外一个服务,而另外一个服务的裸露工夫比拟迟缓,那么咱们就能够把以后对外裸露的服务进行提早裸露,这样就能够缩小当调用依赖服务时呈现超时异样的状况。

4. 示例演示

咱们同样以获取图书列表为例来进行演示。我的项目构造如下:

因为提早服务裸露是配置服务提供端,所有咱们这里只看服务提供者的 XML 配置dubbo-provider-xml.xml

<?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秒钟后才开始裸露服务。其注解配置也是相似就不再演示。

5. 实现原理

上面咱们简略的通过服务裸露的源码进行剖析。咱们都晓得当 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)应用延时调度器进行服务裸露。

6. 小结

在本大节中咱们次要学习了 Dubbo 中提早服务裸露以及应用形式,同时也剖析了提早服务裸露实现的原理,其本质上是通过提早调度器进行服务裸露,其中提早调度器是关键所在。

本节课程的重点如下:

  1. 了解 Dubbo 提早服务裸露
  2. 理解了提早服务裸露的应用形式
  3. 理解提早服务裸露应用场景
  4. 理解 提早服务裸露实现原理

作者

集体从事金融行业,就任过易极付、思建科技、某网约车平台等重庆一流技术团队,目前就任于某银行负责对立领取零碎建设。本身对金融行业有强烈的喜好。同时也实际大数据、数据存储、自动化集成和部署、散布式微服务、响应式编程、人工智能等畛域。同时也热衷于技术分享创建公众号和博客站点对常识体系进行分享。关注公众号:青年IT男 获取最新技术文章推送!

博客地址: http://youngitman.tech

微信公众号: