Dubbo3
[TOC]
服务导出
当我们在某个接口上加上@DubboService后,就表示定义了一个Dubbo服务,启动应用的时候就会扫描到,并且解析对应的类,得到相对服务的配置信息:
服务的类型
服务的具体实现类
服务的Version、Timeout等等(也就是
@DubboService里面配置的信息)
解析完过后就会把这些配置信息封装成一个ServiceConfig对象,并调用export()进行服务的导出
所谓的服务导出,其实就是做三件事情:
确定服务的最终参数配置
按照不同的协议启动不同的服务器
将服务进行注册,注册到注册中心
确定参数
这一个环节其实就是,确定好我们配置的参数:
在application里面配置的:name、protocol、timout……
在
@DubboService里面配置的: version之类的接口级别的信息
最终确定出服务的各种参数
服务注册
当确定好最终的配置参数过后,Dubbo就会根据配置信息生成对应 服务URL:
URL包括了服务的:ip、port、协议、服务名……
URL也确定了,是时候把这个URL存到注册中心里面去了
但是服务注册不仅仅这样简单了, 他需要注意:
如果配置信息改变了,消费者要如何感知到
change呢消费者要怎么知道现在他要用的某个Dubbo服务,是哪一个呢
……
应用级注册
在Dubbo3.0之前,Dubbo进行的都是接口级注册,每个接口在注册中心(ZK)上都会有一个字符串
在Dubbo3.0之后,他兼容了以前的接口级注册,但同时提供了应用级的注册:
其中:
key是接口名,value就是服务URL
那么为什么好端端的,要学SpringCloud Nacos那套,应用级注册呢?
来看看:
一个分布式系统接口调用,就会存在就是说:一个应用中有3个Dubbo服务,那么每增加一个实例,就会向注册中心添加3条记录,那如果一个应用中有10个Dubbo服务,那么每增加一个实例,就会向注册中心添加10条记录,注册中i心的压力随着应用实例的增加而剧烈增加。
所以为了降低注册中心的压力,Dubbo3选择支持应用级注册,同时也兼容接口级注册,用户可逐步迁移称应用级注册
上面提到:
消费者要怎么知道现在他要用的某个Dubbo服务,是哪一个呢
在进行服务到处的过程中,会在ZK中存一个映射关系,在服务到导出的最后一步,ServiceConfig的exported()方法保存了这个映射关系:
其中mapServiceName(url, serviceNameMapping, scheduledExecutor);保存了映射关系
消费者知道了要使用的Dubbo服务在哪个应用,那也就可以从注册中心中根据应用名查到应用的所有实例信息。但是在真正发送请求之前,还得知道服务的配置信息,对与消费者而言,他得知道当前要调用的这个Dubbo服务支持什么协议、timeout是多少……那么这个配置信息从上面最开始说到了,他们已经被注册到了注册中心了。
那么应用级注册是如何实现的呢?
首先,需要通过配置application里面来选择自己是要接口等级还是应用级注册,,当调用RegistryProtocol的export()方法处理registry://时,会利用ZookeeperRegistry把服务URL注册到Zookeeper中去,这就是接口级注册。
在ServiceDiscoveryRegistry里面的doRegistry(URL url)方法,就是应用级注册
这个方法做了两件事情:
将传进来的url进行处理
对处理过后的url进行注册
那么再来看看这个register方法吧:
再进去:
可以看出来,就是吧传进来的url构造出ServiceInfo对象放到services里面,一个MetadataInfo对象就存储以上的信息
前面提到过,在应用启动的最后,才会进行应用级注册,而应用级注册就是当前的应用实例上相关的信息存入注册中心, 包括:
应用的名字
获取与应用元数据的方式
当前实例的ip和port
当前实例支持的协议以及对应的端口
那么如果存在这样的一种情况呢:一个实例支持多个协议以及多个端口,呢么如何确定实例的ip和port?
就像这样:
如果是这样,最终存入endpoint中的会保证一个协议只对应一个端口,另外那个将被忽略,最终服消费者在进行服务引入的时候就会用到这个endpoint信息
在Dubbo2.7中就有了元数据中心,它其实就是减轻注册中心的压力的,Dubbo会把服务信息完整的存一份到元数据中心,元数据中心也可以用ZK来实现,自傲暴露完元数据服务之后,在注册实例信息到注册中心之前,就会把MetadataInfo存入元数据中心。
总结一下:
在导出某个Dubbo服务URL时,会把服务URL存入MetadataInfo中(ServiceConfig)
根据不同的协议,启动不同的服务器
将URL存入MetadataInfo中
所有服务都存入过后,将(接口:应用名)存入元数据中心
应用级注册
Remote:将MedatadaInfo对象存入元数据中心
Local:启动导出元数据服务(默认dubbo协议,端口20880)
确定实例port
确定
dubbo.endpoints确定实例编号revision
将实例对象存入注册中心
服务引入
服务引入就是通过引入加了@DubboReference注解的类的代理对象
通过ReferenceConfig的get()方法得到一个当前接口的代理对象
然后通过RegistryProtocol.doRefer()方法返回一个MigrationInvoker对象:
接着通过MigrationRule.getStep()方法对step进行赋值:
反正最终就是得到一个基于MigrationInvoker的接口代理对象
服务调用
在引入服务之后,通过接口代理对象执行方法:执行MigrationInvoker.invoke()方法,去除currentAvailableInvoker属性对应的ClusterInvoker,然后执行ClusterInvoker.invoke方法,最后通过负载均衡根据不同的协议发送不同的数据包
Last updated