dubbo源码阅读-服务订阅(八)之远程订阅(dubbo)

说明

《服务订阅主流程》可以看到根据协议来注册 我们默认没有根据url直接配置所以url是registry SPI扩展就是走的RegistryProtocol

RegistryProtocol

<1>refer

 /**
     * type为订阅接口
     * @param type Service class
     * @param url  URL address for the remote service
     * @param <T>
     * @return
     * @throws RpcException
     */
    @Override
    @SuppressWarnings("unchecked")
    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
        //删除registry协议 并获取url订阅协议默认dubbo 如果配置的注册中心是zookeeper://name协议就是zookeeper
        url = url.setProtocol(url.getParameter(Constants.REGISTRY_KEY, Constants.DEFAULT_REGISTRY)).removeParameter(Constants.REGISTRY_KEY);
        //@SPI实现  获得对应的registry实现
        Registry registry = registryFactory.getRegistry(url);
        if (RegistryService.class.equals(type)) {
            return proxyFactory.getInvoker((T) registry, type, url);
        }

        // group="a,b" or group="*"
        //将url参数 转换为 map
        Map<String, String> qs = StringUtils.parseQueryString(url.getParameterAndDecoded(Constants.REFER_KEY));
        //获取group   https://blog.csdn.net/weixin_43868594/article/details/84956886
        String group = qs.get(Constants.GROUP_KEY);
        //如果配置了group
        if (group != null && group.length() > 0) {
            if ((Constants.COMMA_SPLIT_PATTERN.split(group)).length > 1
                    || "*".equals(group)) {
                //<2>使用mergeable
                return doRefer(getMergeableCluster(), registry, type, url);
            }
        }
        //<2>cluster为SPI扩展 默认FailoverCluster 为集群策略
        return doRefer(cluster, registry, type, url);
    }

<2>doRefer

 private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
        //type为订阅接口类型 url为订阅url
        //zookeeper://IP:2181/com.alibaba.dubbo.registry.RegistryService?**
        RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
        directory.setRegistry(registry);
        directory.setProtocol(protocol);
        // all attributes of REFER_KEY
        //获取参数
        Map<String, String> parameters = new HashMap<String, String>(directory.getUrl().getParameters());

        //订阅url
        URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, parameters.remove(Constants.REGISTER_IP_KEY), 0, type.getName(), parameters);
        if (!Constants.ANY_VALUE.equals(url.getServiceInterface())
                && url.getParameter(Constants.REGISTER_KEY, true)) {
            URL registeredConsumerUrl = getRegisteredConsumerUrl(subscribeUrl, url);
            //将订阅url 添加到已注册列表 registryList
            registry.register(registeredConsumerUrl);
            //设置到directory
            directory.setRegisteredConsumerUrl(registeredConsumerUrl);
        }
        //<3>订阅服务 内部调用registry.subscribe
        directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
                Constants.PROVIDERS_CATEGORY
                        + "," + Constants.CONFIGURATORS_CATEGORY
                        + "," + Constants.ROUTERS_CATEGORY));

        //通过集群策略包装成一个Invoker返回
        Invoker invoker = cluster.join(directory);
        //注册到订阅列表
        ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory);
        return invoker;
    }

<3>subscribe

 public void subscribe(URL url) {
        //此时的url为:consumer://192.168.2.1/com.alibaba.dubbo.demo.DemoService?*
        setConsumerUrl(url);
         //对应的注册中心实现类 调用订阅方法 通知添加监听器 就是当前对象 实现了 NotifyListener
        registry.subscribe(url, this);
    }

原文地址:https://www.cnblogs.com/LQBlog/p/12502522.html

时间: 2024-11-06 03:55:29

dubbo源码阅读-服务订阅(八)之远程订阅(dubbo)的相关文章

dubbo源码阅读笔记--服务调用时序

上接dubbo源码阅读笔记--暴露服务时序,继续梳理服务调用时序,下图右面红线流程. 整理了调用时序图 分为3步,connect,decode,invoke. 连接 AllChannelHandler.connected(Channel) line: 38 HeartbeatHandler.connected(Channel) line: 47 MultiMessageHandler(AbstractChannelHandlerDelegate).connected(Channel) line:

【Dubbo源码阅读系列】服务暴露之远程暴露

引言 什么叫 远程暴露 ?试着想象着这么一种场景:假设我们新增了一台服务器 A,专门用于发送短信提示给指定用户.那么问题来了,我们的 Message 服务上线之后,应该如何告知调用方服务器,服务器 A 提供了 Message 功能?那么我们是不是可以把目前已提供的服务暴露在一个地方,让调用方知道某台机器提供了某个特定功能?带着这样的假设,我们今天就来聊聊 Dubbo 服务暴露之远程暴露!! 服务远程暴露 先回顾一下上篇文章,上篇文章我们聊到了 ServiceConfig 的 export() 方

【Dubbo源码阅读系列】之远程服务调用(上)

今天打算来讲一讲 Dubbo 服务远程调用.笔者在开始看 Dubbo 远程服务相关源码的时候,看的有点迷糊.后来慢慢明白 Dubbo 远程服务的调用的本质就是动态代理模式的一种实现.本地消费者无须知道远程服务具体的实现,消费者和提供者通过代理类来进行交互!! 一.JAVA 动态代理 简单看一段代码回顾一下动态代理: public class MyInvocationHandler implements InvocationHandler{ private Object object; publi

Dubbo 源码分析 - 服务导出全过程解析

1.服务导出过程 本篇文章,我们来研究一下 Dubbo 导出服务的过程.Dubbo 服务导出过程始于 Spring 容器发布刷新事件,Dubbo 在接收到事件后,会立即执行服务导出逻辑.整个逻辑大致可分为三个部分,第一是前置工作,主要用于检查参数,组装 URL.第二是导出服务,包含导出服务到本地 (JVM),和导出服务到远程两个过程.第三是向注册中心注册服务,用于服务发现.本篇文章将会对这三个部分代码进行详细的分析,在分析之前,我们先来了解一下服务的导出过程. Dubbo 支持两种服务导出方式,

dubbo源码之四——服务发布二

dubbo版本:2.5.4 2. 服务提供者暴露一个服务的详细过程 上图是服务提供者暴露服务的主过程: 首先ServiceConfig类拿到对外提供服务的实际类ref(如:HelloWorldImpl),然后通过ProxyFactory类的getInvoker方法使用ref生成一个AbstractProxyInvoker实例,到这一步就完成具体服务到Invoker的转化.接下来就是Invoker转换到Exporter的过程. Dubbo处理服务暴露的关键就在Invoker转换到Exporter的

dubbo源码阅读-阅读前的准备(一)

说明 之前自己看了一篇dubbo源码,但是对整体还是没有清晰的了解所以重新跟着别人的博文整理一遍 获取源码 github代码fork 1.打开https://github.com/alibaba/dubbo fork到自己仓库,为了后续自己看的过程中会写一些自己的注释 从自己仓库将项目拉取到本地 模块划分 项目结构一览 官方dubbo框架设计文档地址 dubbo-common 提供 Util 类和通用模型 dubbo-remoting 远程通信模块:提供通用的客户端和服务端的通讯功能. 原文地址

dubbo源码阅读之服务导出

dubbo服务导出 常见的使用dubbo的方式就是通过spring配置文件进行配置.例如下面这样 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns

Dubbo源码学习--服务发布(ProxyFactory、Invoker)

上文分析了Dubbo服务发布的整体流程,但服务代理生成的具体细节介绍得还不是很详细.下面将会接着上文继续分析.上文介绍了服务代理生成的切入点,如下: Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url); 这里的proxyFactory是在ServiceConfig中定义的,是final类型静态变量,赋值后无法进行修改.如下: private static final ProxyFactor

Dubbo源码阅读笔记3

### 扩展点加载(ExtensionLoader) 每一种类型的扩展点都有一个ExtensionLoader实例 变量说明 public class ExtensionLoader<T> { // dubbo服务扫描目录 private static final String SERVICES_DIRECTORY = "META-INF/services/"; // dubbo扩展点配置扫描目录(自定义扩展时使用此目录) private static final Stri