Dubbo源码解析(二)-以zookeeper为注册中心,深入了解服务调用方消费者注册以及调用

本文深入解析了Dubbo服务调用方如何在Zookeeper作为注册中心的环境中进行消费者注册及服务调用。通过ReferenceBean初始化,创建消费者临时节点,订阅服务提供者节点,并详细阐述了连接建立、invoker的生成过程,以及异步结果的获取。总结了消费者在获取服务实例时与服务端建立长连接,通过请求对象发送调用,等待服务端响应的流程。
摘要由CSDN通过智能技术生成

上篇讲了服务提供方暴露出对应的接口后,以及在zookeeper中创建了provider节点,https://blog.csdn.net/qq_38340127/article/details/112698774接下来继续服务调用方调试。

xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <dubbo:application name="demo-consumer"/>

    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

    <!-- generate proxy for the remote service, then demoService can be used in the same way as the
    local regular interface -->
    <dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.demo.DemoService"/>

</beans>

reference对应

registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));

通过对ReferenceBean(implements FactoryBean说明为一个生成bean的对象,那么具体get就是通过该对象的getObject方法)进行调试查看

org.apache.dubbo.config.spring.ReferenceBean#getObject

    @Override
    public Object getObject() {
        return get();
    }
通过get方法得到对应的ref
    public synchronized T get() {
        checkAndUpdateSubConfigs();

        if (destroyed) {
            throw new IllegalStateException("The invoker of ReferenceConfig(" + url + ") has already destroyed!");
        }
        if (ref == null) {
            init();
        }
        return ref;
    }

可以看出主要操作为init()

对init进行解析可以看出先是一系列的判断和生成对应的map

然后根据map代理生成ref

ref = createProxy(map);

本次案例生成的map为:分别对应方法和接口等信息

        // 判断是否为本地调用,若为本地调用
        if (shouldJvmRefer(map)) {
            URL url = new URL(LOCAL_PROTOCOL, LOCALHOST_VALUE, 0, interfaceClass.getName()).addParameters(map);
            invoker = REF_PROTOCOL.refer(interfaceClass, url);
            if (logger.isInfoEnabled()) {
                logger.info("Using injvm service " + interfaceClass.getName());
            }
        } 


        
            // 可能又多个注册中心,如果只有一个则直接进行refer 本次案例中只有1个所以直接走第一个
            if (urls.size() == 1) {
                invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0));
            } else {
                List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
                URL registryURL = null;
                for (URL url : urls) {
                    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
                    URL u = registryURL.addParameter(CLUSTER_KEY, RegistryAwareCluster.NAME);
                    // The invoker wrap relation would be: RegistryAwareClusterInvoker(StaticDirectory) -> FailoverClusterInvoker(RegistryDirectory, will execute route) -> Invoker
                    invoker = CLUSTER.join(new StaticDirectory(u, invokers));
                } else { // not a registry url, must be direct invoke.
                    invoker = CLUSTER.join(new StaticDirectory(invokers));
                }
            }

深入refer方法可以得到:

    private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
        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 subscribeUrl = new URL(CONSUMER_PROTOCOL, parameters.remove(REGISTER_IP_KEY), 0, type.getName(), parameters);
        if (!ANY_VALUE.equals(url.getServiceInterface()) && url.getParameter(REGISTER_KEY, true)) {
            directory.setRegisteredConsumerUrl(getRegisteredConsumerUrl(subscribeUrl, url));
            registry.register(directory.getRegisteredConsumerUrl());
        }
        directory.buildRouterChain(subscribeUrl);
        // 通过订阅的模式
        directory.subscribe(subscribeUrl.addParameter(CATEGORY_KEY,
                PROVIDERS_CATEGORY + "," + CONFIGURATORS_CATEGORY + "," + ROUTERS_CATEGORY));

        Invoker invoker = cluster.join(directory);
        ProviderConsumerRegTable.reg
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
服务消费者调用失败可能有多种原因,具体需要根据你的具体情况来分析。以下是一些可能导致服务消费者调用失败的常见问题和解决法: 1. 检查服务提供者是否已经成功注册ZooKeeper。你可以使用 ZooKeeper 的命令行工具或可视化工具来检查服务提供者是否已经成功注册。如果服务提供者没有成功注册,那么服务消费者将无法找到该服务调用也会失败。 2. 检查服务消费者是否正确引用了服务提供者的接口。服务消费者调用服务提供者时,需要正确引用服务提供者的接口,否则将无法调用成功。你可以检查服务消费者代码中引用服务提供者接口的地,确保其与服务提供者的接口一致。 3. 检查服务消费者的网络连接是否正常。服务消费者需要能够正确连接到 ZooKeeper服务提供者,才能调用服务。你可以检查服务消费者的网络连接是否正常,确保其可以与 ZooKeeper服务提供者建立连接。 4. 检查服务提供者的配置是否正确。服务提供者的配置可能会影响服务消费者调用。你可以检查服务提供者的配置项,确保其与服务消费者的配置一致。 5. 检查服务提供者的实现是否正确。如果服务提供者的实现有问题,可能会导致服务消费者调用失败。你可以检查服务提供者的实现代码,确保其正确实现了服务接口。 希望这些提示能够帮助你解决问题。如果你需要更多的帮助,请提供更多的上下文和错误信息,我会尽力为你提供帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值