Dubbo服务引用解析

Dubbo服务调用详解:客户端代理生成与服务发现流程

上一次我们讲解了Dubbo的服务暴露, 这次我们来看一下Dubbo是如何调用服务的


本文会根据dubbo的架构图进行解析

目录

客户端启动流程

Dubbo服务调用


客户端启动流程

大家都知道,客户端在调用服务时只有接口没有相对应的实现类,所以呢,我们需要在调用服务时需要先生成一个代理,再通过代理去执行服务。

        

 可以看到我们通过从ioc中获取DemoService的Bean,那其实本身客户端中并没有DemoService的bean,这个时候我们可以看到配置文件中进行了这样的一个配置使用了reference标签,在dubbo中reference标签配置的服务会被另一个Bean生成代理,那就是ReferenceBean,它会通过getObject()方法将生成的代理对象放入ioc中,所以点进去

<dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.demo.DemoService"/>

 这里会对接口的代理对象进行检查,如果没有则会初始化一个

public synchronized T get() {
        checkAndUpdateSubConfigs();

        if (destroyed) {
            throw new IllegalStateException("The invoker of ReferenceConfig(" + url + ") has already destroyed!");
        }
        // 检测 ref 是否为空,为空则通过 init 方法创建
        if (ref == null) {
            // init 方法主要用于处理配置,以及调用 createProxy 生成代理类
            init();
        }
        return ref;
    }

点进init()方法中,可以看到核心的方法就是创建代理对象的(能看到我们本身配置的一些信息,接口路径等等)

接着就是对提供者的数量的一个判断,是有多个还是单个,然后生成invoker,最后会根据invoker返回生成的代理,重点则在于如何生成invoker,这里的protocol是自适应的,所以会根据url中的信息选择对应的实现类,可以看到协议中使用的是registry,于是来到RegistryProtocol

            // 单个注册中心或服务提供者(服务直连,下同)
            if (urls.size() == 1) {
                // 调用 RegistryProtocol 的 refer 构建 Invoker 实例
                invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0)); // registry://192.168.200.129:2181/org.apache.dubbo.registry.RegistryService?application=demo-consumer&dubbo=2.0.2&pid=14276&qos.port=33333&refer=application%3Ddemo-consumer%26check%3Dfalse%26dubbo%3D2.0.2%26interface%3Dorg.apache.dubbo.demo.DemoService%26lazy%3Dfalse%26methods%3DsayHello%26pid%3D14276%26qos.port%3D33333%26register.ip%3D192.168.200.10%26side%3Dconsumer%26sticky%3Dfalse%26timestamp%3D1622603489641&registry=zookeeper&timestamp=1622603494381
            } else {
                // 多个注册中心或多个服务提供者,或者两者混合
                List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
                URL registryURL = null;
                // 获取所有的 Invoker 到 invokers中
                for (URL url : urls) {
                    // 通过 ref_protocol 调用 refer 构建 Invoker,refprotocol 会在运行时
                    // 根据 url 协议头加载指定的 Protocol 实例,并调用实例的 refer 方法
                    invokers.add(REF_PROTOCOL.refer(interfaceClass, url));
                    if (REGISTRY_PROTOCOL.equals(url.getProtocol())) {
                        registryURL = url; // use last registry url
                    }
                }
                if (registryURL != null) { // registry url is available
                    // use RegistryAwareCluster only when register's CLUSTER is available
                    // 如果注册中心链接不为空,则将使用 AvailableCluster
                    URL u = registryURL.addParameter(CLUSTER_KEY, RegistryAwareCluster.NAME);
                    // The invoker wrap relation would be: RegistryAwareClusterInvoker(StaticDirectory) -> FailoverClusterInvoker(RegistryDirectory, will execute route) -> Invoker
                    // 创建 StaticDirectory 实例,并由 Cluster 对多个 Invoker 进行合并  Cluster扩展点默认找的是FailoverCluster
                    invoker = CLUSTER.join(new StaticDirectory(u, invokers));
                } else { // not a registry url, must be direct invoke.
                    invoker = CLUSTER.join(new StaticDirectory(invokers));
                }
            }

// invoker 可用性检查
        if (shouldCheck() && !invoker.isAvailable()) {
            throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + (group == null ? "" : group + "/") + interfaceName + (version == null ? "" : ":" + version) + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion());
        }
        if (logger.isInfoEnabled()) {
            logger.info("
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值