一:入口
- 在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));
}
}
如果遇到
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的属性中。