Dubbo Multicast 注册中心即相关代码实现
Dubbo 的 Multicast注册中心有下面特点:
- 不需要启动任何中心节点,只要广播地址一样,就可以互相发现
- 组播受网络结构限制,只适合小规模应用或开发阶段使用。
- 组播地址段: 224.0.0.0 - 239.255.255.255
有关组播的相关资料可以参考后面文章: http://www.cnblogs.com/ghj1976/p/5276452.html
广播时的流程图如下:
- 提供方启动时广播自己的地址。
- 消费方启动时广播订阅请求。
- 提供方收到订阅请求时,单播自己的地址给订阅者,如果设置了unicast=false,则广播给订阅者。
- 消费方收到提供方地址时,连接该地址进行RPC调用。
我们用Wireshark来监控这个过程。
这时候的过滤条件是: ip.dst=224.0.0.0/4 这个ip地址段是广播的地址段, 参考: http://stackoverflow.com/questions/11400046/wireshark-filter-by-multicast-in-gui
第一个发出的包,我们可以看到是注册 UDP的包, 核心内容如下:
register dubbo://10.37.129.2:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.5.4-SNAPSHOT&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&pid=3651&revision=2.5.4-SNAPSHOT&side=provider×tamp=1459131958710
随后一个订阅 UDP包。
subscribe provider://10.37.129.2:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.5.4-SNAPSHOT&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&pid=3651&revision=2.5.4-SNAPSHOT&side=provider×tamp=1459131958710
当消费者启动时,广播了下面信息:
register consumer://10.37.129.2/com.alibaba.dubbo.demo.DemoService?application=demo-consumer&category=consumers&check=false&dubbo=2.5.4-SNAPSHOT&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=3803&revision=2.5.4-SNAPSHOT&side=consumer×tamp=1459134194229
subscribe consumer://10.37.129.2/com.alibaba.dubbo.demo.DemoService?application=demo-consumer&category=providers,configurators,routers&dubbo=2.5.4-SNAPSHOT&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=3803&revision=2.5.4-SNAPSHOT&side=consumer×tamp=1459134194229
通过这样的方式,生产者和消费者都知道了对方,然后就是具体调用了。
具体调用,则是会返回下面2个内容的 TCP 包
2.5.4-SNAPSHOT0"com.alibaba.dubbo.demo.DemoService0.0.0sayHelloLjava/lang/String;world89Hpath0"com.alibaba.dubbo.demo.DemoService interface0"com.alibaba.dubbo.demo.DemoServiceversion0.0.0Z
08Hello world89, response form provider: 10.37.129.2:20880
这部分注册的代码,我们可以在 github/alibaba/dubbo/dubbo-registry/dubbo-registry-multicast/src/main/java/com/alibaba/dubbo/registry/multicast/MulticastRegistry.java 这里看到。
整个注册相关的接口如下,这里只是提取 dubbo-registry-api 的其中 RegisterService 接口部分:
/**
* RegistryService. (SPI, Prototype, ThreadSafe)
*
* @see com.alibaba.dubbo.registry.Registry
* @see com.alibaba.dubbo.registry.RegistryFactory#getRegistry(URL)
* @author william.liangf
*/
public interface RegistryService {/**
* 注册数据,比如:提供者地址,消费者地址,路由规则,覆盖规则,等数据。
*
* 注册需处理契约:<br>
* 1. 当URL设置了check=false时,注册失败后不报错,在后台定时重试,否则抛出异常。<br>
* 2. 当URL设置了dynamic=false参数,则需持久存储,否则,当注册者出现断电等情况异常退出时,需自动删除。<br>
* 3. 当URL设置了category=routers时,表示分类存储,缺省类别为providers,可按分类部分通知数据。<br>
* 4. 当注册中心重启,网络抖动,不能丢失数据,包括断线自动删除数据。<br>
* 5. 允许URI相同但参数不同的URL并存,不能覆盖。<br>
*
* @param url 注册信息,不允许为空,如:dubbo://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
*/
void register(URL url);/**
* 取消注册.
*
* 取消注册需处理契约:<br>
* 1. 如果是dynamic=false的持久存储数据,找不到注册数据,则抛IllegalStateException,否则忽略。<br>
* 2. 按全URL匹配取消注册。<br>
*
* @param url 注册信息,不允许为空,如:dubbo://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
*/
void unregister(URL url);/**
* 订阅符合条件的已注册数据,当有注册数据变更时自动推送.
*
* 订阅需处理契约:<br>
* 1. 当URL设置了check=false时,订阅失败后不报错,在后台定时重试。<br>
* 2. 当URL设置了category=routers,只通知指定分类的数据,多个分类用逗号分隔,并允许星号通配,表示订阅所有分类数据。<br>
* 3. 允许以interface,group,version,classifier作为条件查询,如:interface=com.alibaba.foo.BarService&version=1.0.0<br>
* 4. 并且查询条件允许星号通配,订阅所有接口的所有分组的所有版本,或:interface=*&group=*&version=*&classifier=*<br>
* 5. 当注册中心重启,网络抖动,需自动恢复订阅请求。<br>
* 6. 允许URI相同但参数不同的URL并存,不能覆盖。<br>
* 7. 必须阻塞订阅过程,等第一次通知完后再返回。<br>
*
* @param url 订阅条件,不允许为空,如:consumer://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
* @param listener 变更事件监听器,不允许为空
*/
void subscribe(URL url, NotifyListener listener);/**
* 取消订阅.
*
* 取消订阅需处理契约:<br>
* 1. 如果没有订阅,直接忽略。<br>
* 2. 按全URL匹配取消订阅。<br>
*
* @param url 订阅条件,不允许为空,如:consumer://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
* @param listener 变更事件监听器,不允许为空
*/
void unsubscribe(URL url, NotifyListener listener);/**
* 查询符合条件的已注册数据,与订阅的推模式相对应,这里为拉模式,只返回一次结果。
*
* @see com.alibaba.dubbo.registry.NotifyListener#notify(List)
* @param url 查询条件,不允许为空,如:consumer://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
* @return 已注册信息列表,可能为空,含义同{@link com.alibaba.dubbo.registry.NotifyListener#notify(List<URL>)}的参数。
*/
List<URL> lookup(URL url);}
参考:http://dubbo.io/Multicast+Registry-zh.htm
为了减少广播量,Dubbo缺省使用单播发送提供者地址信息给消费者,
如果一个机器上同时启了多个消费者进程,消费者需声明unicast=false,否则只会有一个消费者能收到消息: