服务导出原理总结
- 核心源码入口:ServiceBean.export()
- Spring启动用完后,通过接收ContextRefreshedEvent事件来触发export()方法执行
- 一个ServiceBean即代表一个服务,其对象中的属性即为服务的参数
- 服务的参数值都来自于@Service注解、全局应用、JVM参数、配置中心配置等
- 服务导出逻辑
- 根据服务参数,启动对应的网络服务器(netty,Tomcat,jetty等),用于接收网络请求
- 将服务的基本信息注册到注册中心服务(主要是服务名称、协议,IP,端口及其他相关参数)
- 最后向注册中心(或配置中心)注册监听器,监听Dubbo中动态配置信息的变更
服务的概念
- XxxxService接口、XxxxServiceImpl接口实现分别表示一个服务和服务的具体实现
- 但一个完整的服务,应该包括服务访问协议、地址、端口、名字、分组、版本等属性
- 这些属性组成一个URL,此时这个URL也可称为一个服务
- URL表示远程机器可通过该URL来访问服务
- URL除此以外可能还包含超时时间,所属应用等等其他参数
服务导出的思路
- 确定服务的参数(主要考虑参数获取渠道及其优先级)
- 确定服务支持的协议
- 构造出服务最终的URL
- 将URL注册到注册中心
- 根据不同协议,启动不同Server,接收和处理请求
- 完成服务的导出后,还需绑定一个监听器,监听动态参数的变化
- dubbo支持动态刷新服务配置参数,参数变化后,将重新导出服务,移除老的服务
- 服务重新导出不会导致重新启动Server
服务监听器
- 如果用zk作为配置中心,主要是利用其watcher机制
- 服务监听器ServiceConfigurationListener会监听到节点内容的变化,从而触发一个Spring事件
- 封装的ConfigChangeEvent用于接收事件的内容
- 事件类型包括Added、Modified、Deleted三种,不同类型分别对应不同处理逻辑
- 根据监听到的内容,重新构造新的newUrl,并和currentURL比对
- 若相等,则无需做其他逻辑
- 若不相等,则重新导出服务(currentURL从注册中心移除,然后注册新的newURL)
服务引入的核心原理
- Spring启动中,会给@Reference注解标记的属性进行赋值
- 赋值对象为ReferenceBean.get()返回的值,该对象为一个代理对象
- get()逻辑主要内容
- 检查和更新参数(与服务提供者类似)
- 根据参数,将所引入的服务设置的参数放到map中
- 根据该map去注册中心获取服务列表
- 若注册中心只有一个,则得到一个invoker对象
- 若有多个注册中心,则遍历每个注册中心,得到一个个invoker,并放入invokers中
- 最终通过invoker对象调用PROXY_FACTORY.getProxy(invoker),生成代理对象ref
- invoker对象总结来说,就是一个服务的执行者
服务目录
- 消费端每个引入的服务,对应一个服务目录(RegistryDirectory)
- 一个RegistryDirectory包含
- serviceType:服务接口
- serviceKey:serviceClass + version + group
- queryMap:引入服务的参数配置
- configurators:动态配置
- routerChain:路由链
- invokers:当前引入服务对应缓存的服务提供者Invoker
- 两个监听器,分别监听消费者应用本身的动态配置与所引入服务的动态配置
各种Invoker实现类提供的能力
- 完成Mock功能:MockClusterInvoker
- 完成集群容错功能:FailoverClusterInvoker
- 选择注册中心:RegistryAwareClusterInvoker
- 完成对应协议的服务调用:DubboInvoker
- 完成对过滤器的调用:ProtocolFilterWrapper、CallbackRegistrationInvoker
发起服务调用
- 消费者通过DubboInvoker发起服务调用
- 底层使用NioSocketChannel发起请求(传过去invocation对象),同时还会建立心跳
- 服务提供者通过NettyServerHandler接收到请求
- 调用一系列数据解码,处理完业务逻辑后,将数据再编码
- 最后通过封装的AppResponse,将请求处理的结果响应给服务消费者
- 通过NettyClientHandler接收响应
- 对响应结果进行解码,并处理后续逻辑
- 调用过程中支持同步调用与异步调用两类,细节逻辑有较多差异
- 默认为同步调用