Dubbo Multicast 注册中心即相关代码实现

Dubbo 的 Multicast注册中心有下面特点:

  • 不需要启动任何中心节点,只要广播地址一样,就可以互相发现
  • 组播受网络结构限制,只适合小规模应用或开发阶段使用。
  • 组播地址段: 224.0.0.0 - 239.255.255.255

有关组播的相关资料可以参考后面文章: http://www.cnblogs.com/ghj1976/p/5276452.html

 

image

广播时的流程图如下:

  1. 提供方启动时广播自己的地址。
  2. 消费方启动时广播订阅请求。
  3. 提供方收到订阅请求时,单播自己的地址给订阅者,如果设置了unicast=false,则广播给订阅者。
  4. 消费方收到提供方地址时,连接该地址进行RPC调用。

 

我们用Wireshark来监控这个过程。

这时候的过滤条件是: ip.dst=224.0.0.0/4  这个ip地址段是广播的地址段, 参考: http://stackoverflow.com/questions/11400046/wireshark-filter-by-multicast-in-gui 

image 

第一个发出的包,我们可以看到是注册 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&timestamp=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&timestamp=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&timestamp=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&timestamp=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

image

 

这部分注册的代码,我们可以在  github/alibaba/dubbo/dubbo-registry/dubbo-registry-multicast/src/main/java/com/alibaba/dubbo/registry/multicast/MulticastRegistry.java  这里看到。

image

整个注册相关的接口如下,这里只是提取 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,否则只会有一个消费者能收到消息:

原文地址:https://www.cnblogs.com/ghj1976/p/5328376.html