Dubbo源码解析 之 Provider暴露服务

前言

Dubbo Provider暴露服务的流程中,需要掌握几个核心抽象对象

  • 过程中的重要类

    • ServiceConfig:记录了Dubbo Service所有相关的配置信息。ServiceConfig作用
    • DubboProtocol:以Dubbo协议的方式暴露服务,并以此为中心维护所有相关的动态服务数据。
    • RegisterProtocol: 内部会加载具体的注册中心Register,例如:ZookeeperRegister。完成服务向注册中心注册的动作。
    • ServiceConfig#loadRegistries:解析获得注册中心地址列表
  • 过程中的重要对象

    • com.alibaba.dubbo.common.URL: 服务发布的地址
    • Invoker: 对原Service Interface进行了代理封装,屏蔽了具体Service Interface的差异,方便统一管理和调用。
    • Exporter: 一个ServiceBean每向一个注册中心Register注册一次,就会生成已各Exporter。Exporter用于连接暴露服务的Url与本地Invoker的对应关系。
    • ExporterMap: 记录着服务地址和Exporter的对应关系
  • 来自Dubbo官方的几个架构设计图,先感觉下

在这里插入图片描述

在这里插入图片描述

ServiceBean核心流程

  1. Spring容器启动,带动Dubbo Bean配置解析以及Bean实例化。
    • [Dubbo启动](#Dubbo 启动)
    • 关键类:
  2. ServiceBean 继承了ServiceConfig,所有的Provider服务的Dubbo配置都在ServiceConfig中。
    • Dubbo Service基本信息
    • Dubbo Service参数配置
    • 注册中心地址信息。对应ServiceConfig中的loadRegistries().
  3. ServiceBean 实现了InitializingBean, 实现了afterPropertiesSet()方法,在每个Dubbo Service Bean实例化后,在afterPropertiesSet()方法中进行所有Dubbo服务注册需要的操作。
  4. afterPropertiesSet()中前置代码都是在做一些配置校验和默认值设置,最后会执行export()方法注册暴露服务。
  5. afterPropertiesSet()
    • export()
      • doExport()
        • doExportUrls()
          • doExportUrlsFor1Protocol(DubboProtocol, regitsryURLs)
            • DubboProtocol.export(wrapperInvoker)
  6. doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List registryURLs) 是真正执行export暴露服务的代码区

DubboProtocol#Export核心流程

public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
   
    URL url = invoker.getUrl();

    // export service.
    String key = serviceKey(url);
    DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);
    exporterMap.put(key, exporter);

    //export an stub service for dispatching event
    Boolean isStubSupportEvent = url.getParameter(Constants.STUB_EVENT_KEY, Constants.DEFAULT_STUB_EVENT);
    Boolean isCallbackservice = url.getParameter(Constants.IS_CALLBACK_SERVICE, false);
    if (isStubSupportEvent && !isCallbackservice) {
   
        String stubServiceMethods = url.getParameter(Constants.STUB_EVENT_METHODS_KEY);
        if (stubServiceMethods == null || stubServiceMethods.length() == 0) {
   
            if (logger.isWarnEnabled()) {
   
                logger.warn(new IllegalStateException("consumer [" + url.getParameter(Constants.INTERFACE_KEY) +
                        "], has set stubproxy support event ,but no stub methods founded."));
            }
        } else {
   
            stubServiceMethodsMap.put(url.getServiceKey(), stubServiceMethods);
        }
    }

    //获取一个服务端口,使用NettyServer绑定并监听,并设置Server监听事件处理回调为:DubboProtocol#requestHandler
    //Exchanger.bind的实际对象可配置,对应dubbo-remoting-api包
    openServer(url);   
    optimizeSerialization(url);
    return exporter;
}

DubboProtocol核心数据

public class DubboProtocol extends AbstractProtocol {
   

    ...

    //单例
    private static DubboProtocol INSTANCE;
    
    //本地启动Server监听服务的Map
    private final Map<String, ExchangeServer> serverMap = new ConcurrentHashMap<String, ExchangeServer>(); // <host:port,Exchanger>
    
    //记录消费端的Exchanger
    private final Map<String, ReferenceCountExchangeClient> referenceClientMap = new ConcurrentHashMap<String, ReferenceCountExchangeClient>(); // <host:port,Exchanger>
    
    //
    private final ConcurrentMap<String, LazyConnectExchangeClient> ghostClientMap = new ConcurrentHashMap<String, LazyConnectExchangeClient>();
    
    //
    private final Set<String> optimizers = new ConcurrentHashSet<String>();
    
    //consumer side export a stub service for dispatching event
    //servicekey-stubmethods
    private final ConcurrentMap<String, String> stubServiceMethodsMap = new ConcurrentHashMap<String, String>();
    private ExchangeHandler requestHandler = {
   ...};

    ...

}

public abstract class AbstractProtocol implements Protocol {
   
    // ExporterMap
    protected final Map<String, Exporter<?>> exporterMap = new ConcurrentHashMap<String, Exporter<?>>();
}

Dubbo Service是哪个时机注册到注册中心的?

有关注到这个章节内容的小伙伴,说明你此时可能也还没想通吧,请听我道来。

这里会涉及到Dubbo的SPI机制,Dubbo 有好几个利用SPI+动态代理+Filter的处理责任链模式,ProtocolFilterWrapper.java算一个。
- Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

在Dubbo源码中,Dubbo有自行注册几个protocol SPI (这里只列举Dubbo服务注册相关的)

  • SPI机制用法详见
  • Dubbo Protocol SPI扩展详见
  • RegistryProtocol SPI:
    • 注册位置:dubbo-registry-api包,resources下的com.alibaba.dubbo.rpc.Protocol
    • 注册位置:dubbo-registry-zookeeper包,resources下的com.alibaba.dubbo.register.RegistryFactory

其实,在ServiceConfig中拿到的全局protocol并不直接是DubboProtocol,而是一串Protocol,DubboProtocol只是其中之一,这些Protocol会以责任链的方式逐一被调用

所以,在doExportUrlsFor1Protocol中protocol.export(…)时,会先执行DubboProtocol#export,再执行RegisterProtocol#export,各司其职。

RegisterProtocol中会根据Dubbo Service配置的register地址类型来决定加载哪个具体的RegisterFactory

public void register(URL registryUrl, URL registedProviderUrl) {
   
        //RegisterFactory根据注册中心类型,获取到注册实例,例如ZookeeperRegistry
        Registry registry = registryFactory.getRegistry(registryUrl);
        
        //执行注册,实际对应ZookeeperRegistry#register
        registry.register(registedProviderUrl);
    }

    public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
   
        ...

        if (register) {
   
            register(registryUrl, registedProviderUrl);
            ProviderConsumerRegTable.getProviderWrapper(originInvoker).setReg(true);
        }

        ...
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值