1.1-服务提供者启动流程

一:入口

  • 在dubbo-2.5.3.jar中的META-INF下有一个文件是spring.handlers里面配置了一个类是com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler,这个便是dubbo的入口。(原理可以看spring-schema扩展)
public class DubboNamespaceHandler extends NamespaceHandlerSupport {
    static {
        Version.checkDuplicate(DubboNamespaceHandler.class);
    }
     // 这个类DubboNamespaceHandler 会把xml中配置的一些标签注册为bean解析器,比如说遇到provider这个字符串就会用下面对应的Parser去解析,所以下面的字符串application,module,registry都会对应到不同的Parse实例。
    public void init() {
        registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
        //比如说配置了
        //这个时候就会用DubboBeanDefinitionParser去解析这个标记,然后组装ServiceBean对象。
        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
        registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));
    }

}

如果遇到,解析代码是在DubboBeanDefinitionParser的parse方法中,dubbo-2.5.3.jar的231行。

beanDefinition.getPropertyValues().addPropertyValue(property, reference);

这里的beanDefinition指的是RootBeanDefinition实例,内部的BeanClass是com.alibaba.dubbo.config.spring.ServiceBean,
这里的property, reference分别是interface和com.wang.dubbo.api.PersonService。到此已经可以看到,解析成功,组装了ServiceBean。

二:ServiceBean的启动

  • ServiceBean实现了众多的spring扩展点(InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware,扩展点主要是会在spring容器加载的时候,调用一些钩子方法)
  • ServiceBean中有2个比较核心的方法,是afterPropertiesSet,onApplicationEvent
  • ServiceBean还继承了很多类,这些类是链式的继承关系,每个类都包含了很多属性:如下:
    • ServiceBean
    • ServiceConfig
    • AbstractServiceConfig
    • AbstractInterfaceConfig
    • AbstractMethodConfig
    • AbstractConfig
    • Serializable
2.1 afterPropertiesSet

第一步,设置属性,包括:

  • setProvider(providerConfig);
  • setApplication(applicationConfig);
  • setModule(moduleConfig);
  • super.setRegistries(registryConfigs);
  • setMonitor(monitorConfig);
  • super.setProtocols(protocolConfigs);
  • setPath(beanName);
2.2 onApplicationEvent

该方法会调用export(); 实现真实的服务启动发布

三:export方法

export先做属性等的设置,然后做检查,最后调用doExportUrls。

  • 3.1 loadRegistries:先拿到所有的注册地址:List registryURLs = loadRegistries(true);,然后循环注册地址去注册
  • 3.2 doExportUrlsFor1Protocol: InetAddress.getLocalHost().getHostAddress();(获取本机Ip地址)
  • 3.3 获取本机ip地址,获取端口地址,获取方法名称,获取版本号,获取同步异步等信息组装成Map,然后根据Map生成url:比如说以下URL

dubbo://192.168.122.23:20880/com.wang.dubbo.api.PersonService?anyhost=true&application=Dubbo_HelloWorld&dubbo=2.5.3&interface=com.wang.dubbo.api.PersonService&methods=say&pid=59448&side=provider×tamp=1545891510122

  • 3.4 exportLocal:暴露本地服务(比如说jvm实例内部调用其实不需要走网络,所以这里会先放到本地)
    • 3.4.1 生成本地URL :injvm://127.0.0.1/com.wang.dubbo.api.PersonService?xxxxx(省略)
    • 3.4.2 根据实例(PersonServiceImpl,)接口,URL ,生成Invoker(详情见ProxyFactory:getInvoker),再往里面是JavassistProxyFactory|getInvoker获取Invoker。
    • 生成 Invoker后会包装成Exporter ,把Exporter 放在List> exporters中,该List是ServiceConfig的属性。
  • 3.5 暴露本地服务完了后会根据registryURLs暴露到相关地址上,比如说暴露到zk上。
    • 3.5.1 暴露远程服务也是一样的 Invoker invoker = proxyFactory.getInvoker,Exporter exporter = protocol.export(invoker);先根据proxyFactory获取代理对象,然后根据protocol暴露并且转化为Exporter。

三:protocol.export(invoker) 方法

  • RegistryProtocol|export -> doLocalExport(originInvoker); 该调用会启动netty服务,监听请求。
  • 该方法会对应到一个实现是RegistryProtocol中的export,在这个方法中会读取zk信息,把URL写入ZK。到此过程中一个dubbo服务提供者发布完成。

四:doLocalExport(RegistryProtocol|exporth)

该方法调用到底层会调用到DubboProtocol的export,该方法内部会openServer。 openServer 会启动netty监听端口。
大致的调用链如下(笔记的写法和eclipse的显示上下相反)

  • DubboProtocol:openServer
  • DubboProtocol:createServer
  • Exchangers:bind
  • HeaderExchanger:bind
  • Transporters:bind
  • NettyTransporter:bind
  • new NettyServer(url, listener); 到此接受请求就会进入NettyHandler(该类继承SimpleChannelHandler)

当client调用的时候,拿到请求数据,会解析成Request,然后处理后返回,核心代码在HeaderExchangeHandler中

Response response = handleRequest(exchangeChannel, request);

AbstractProtocol的exporterMap会缓存Exporter,其中key是接口名+端口,比如说com.wang.dubbo.api.PersonService:20880,
然后从Exporter中拿到invoker,invoker.invoke(Invocation inv);返回结果invoke到实际类调用中间会经过非常多的Filter。

最后

dubbo服务者发布过程中的很多信息,都会记录在该ServiceBean的属性中。

你可能感兴趣的:(1.1-服务提供者启动流程)