首页 > 其他分享 >Dubbo之服务禁用启用逻辑

Dubbo之服务禁用启用逻辑

时间:2024-01-29 19:12:36浏览次数:27  
标签:Dubbo map url 禁用 getName 启用 argument KEY method

一、简介

  • 本文主要介绍dubbo 里面和服务disable相关的源码流程,方便以后出问题快速定位原因;
  • 之前是一套注册中心zk集群,dubbo版本2.7.3,dubbo-admin启用禁用没有问题,现在升级dubbo版本为2.7.22,zk集群搞了2套,发现disable和enable没用了,禁用了依然可以调用,遂研究了下关于disable的相关源码,记录一下,方便后续问题排查。
  • 图片看不清楚的滚轮放大把,博客园这块支持的,我吐槽6点......

二、核心流程

2.1 核心流程图

三、服务启动初始化暴露

3.1 DubboBootstrap初始化流程

3.2 DubboBootstrap暴露服务过程

点击查看代码
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs, int protocolConfigNum) {
        String name = protocolConfig.getName();
        if (StringUtils.isEmpty(name)) {
            name = DUBBO;
        }
 
        Map<String, String> map = new HashMap<String, String>();
        map.put(SIDE_KEY, PROVIDER_SIDE);
 
        ServiceConfig.appendRuntimeParameters(map);
        AbstractConfig.appendParameters(map, getMetrics());
        AbstractConfig.appendParameters(map, getApplication());
        AbstractConfig.appendParameters(map, getModule());
        // remove 'default.' prefix for configs from ProviderConfig
        // appendParameters(map, provider, Constants.DEFAULT_KEY);
        AbstractConfig.appendParameters(map, provider);
        AbstractConfig.appendParameters(map, protocolConfig);
        AbstractConfig.appendParameters(map, this);
        MetadataReportConfig metadataReportConfig = getMetadataReportConfig();
        if (metadataReportConfig != null && metadataReportConfig.isValid()) {
            map.putIfAbsent(METADATA_KEY, REMOTE_METADATA_STORAGE_TYPE);
        }
        if (CollectionUtils.isNotEmpty(getMethods())) {
            for (MethodConfig method : getMethods()) {
                AbstractConfig.appendParameters(map, method, method.getName());
                String retryKey = method.getName() + RETRY_SUFFIX;
                if (map.containsKey(retryKey)) {
                    String retryValue = map.remove(retryKey);
                    if (FALSE_VALUE.equals(retryValue)) {
                        map.put(method.getName() + RETRIES_SUFFIX, ZERO_VALUE);
                    }
                }
                List<ArgumentConfig> arguments = method.getArguments();
                if (CollectionUtils.isNotEmpty(arguments)) {
                    for (ArgumentConfig argument : arguments) {
                        // convert argument type
                        if (argument.getType() != null && argument.getType().length() > 0) {
                            Method[] methods = interfaceClass.getMethods();
                            // visit all methods
                            if (methods.length > 0) {
                                for (int i = 0; i < methods.length; i++) {
                                    String methodName = methods[i].getName();
                                    // target the method, and get its signature
                                    if (methodName.equals(method.getName())) {
                                        Class<?>[] argtypes = methods[i].getParameterTypes();
                                        // one callback in the method
                                        if (argument.getIndex() != -1) {
                                            if (argtypes[argument.getIndex()].getName().equals(argument.getType())) {
                                                AbstractConfig
                                                        .appendParameters(map, argument, method.getName() + "." + argument.getIndex());
                                            } else {
                                                throw new IllegalArgumentException(
                                                        "Argument config error : the index attribute and type attribute not match :index :" +
                                                                argument.getIndex() + ", type:" + argument.getType());
                                            }
                                        } else {
                                            // multiple callbacks in the method
                                            for (int j = 0; j < argtypes.length; j++) {
                                                Class<?> argclazz = argtypes[j];
                                                if (argclazz.getName().equals(argument.getType())) {
                                                    AbstractConfig.appendParameters(map, argument, method.getName() + "." + j);
                                                    if (argument.getIndex() != -1 && argument.getIndex() != j) {
                                                        throw new IllegalArgumentException(
                                                                "Argument config error : the index attribute and type attribute not match :index :" +
                                                                        argument.getIndex() + ", type:" + argument.getType());
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        } else if (argument.getIndex() != -1) {
                            AbstractConfig.appendParameters(map, argument, method.getName() + "." + argument.getIndex());
                        } else {
                            throw new IllegalArgumentException(
                                    "Argument config must set index or type attribute.eg: <dubbo:argument index='0' .../> or <dubbo:argument type=xxx .../>");
                        }
 
                    }
                }
            } // end of methods for
        }
 
        if (ProtocolUtils.isGeneric(generic)) {
            map.put(GENERIC_KEY, generic);
            map.put(METHODS_KEY, ANY_VALUE);
        } else {
            String revision = Version.getVersion(interfaceClass, version);
            if (revision != null && revision.length() > 0) {
                map.put(REVISION_KEY, revision);
            }
 
            String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
            if (methods.length == 0) {
                logger.warn("No method found in service interface " + interfaceClass.getName());
                map.put(METHODS_KEY, ANY_VALUE);
            } else {
                map.put(METHODS_KEY, StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));
            }
        }
 
        /**
         * Here the token value configured by the provider is used to assign the value to ServiceConfig#token
         */
        if (ConfigUtils.isEmpty(token) && provider != null) {
            token = provider.getToken();
        }
 
        if (!ConfigUtils.isEmpty(token)) {
            if (ConfigUtils.isDefault(token)) {
                map.put(TOKEN_KEY, UUID.randomUUID().toString());
            } else {
                map.put(TOKEN_KEY, token);
            }
        }
        //init serviceMetadata attachments
        serviceMetadata.getAttachments().putAll(map);
 
        // export service
        String host = findConfigedHosts(protocolConfig, registryURLs, map);
        Integer port = findConfigedPorts(protocolConfig, name, map, protocolConfigNum);
        URL url = new URL(name, host, port, getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), map);
 
        // You can customize Configurator to append extra parameters
        if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
                .hasExtension(url.getProtocol())) {
            url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
                    .getExtension(url.getProtocol()).getConfigurator(url).configure(url);
        }
 
        String scope = url.getParameter(SCOPE_KEY);
        // don't export when none is configured
        if (!SCOPE_NONE.equalsIgnoreCase(scope)) {
 
            // export to local if the config is not remote (export to remote only when config is remote)
            if (!SCOPE_REMOTE.equalsIgnoreCase(scope)) {
                exportLocal(url);
            }
            // export to remote if the config is not local (export to local only when config is local)
            if (!SCOPE_LOCAL.equalsIgnoreCase(scope)) {
                if (CollectionUtils.isNotEmpty(registryURLs)) {
                    for (URL registryURL : registryURLs) {
                        if (SERVICE_REGISTRY_PROTOCOL.equals(registryURL.getProtocol())) {
                            url = url.addParameterIfAbsent(SERVICE_NAME_MAPPING_KEY, "true");
                        }
 
                        //if protocol is only injvm ,not register
                        if (LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
                            continue;
                        }
                        url = url.addParameterIfAbsent(DYNAMIC_KEY, registryURL.getParameter(DYNAMIC_KEY));
                        URL monitorUrl = ConfigValidationUtils.loadMonitor(this, registryURL);
                        if (monitorUrl != null) {
                            url = url.addParameterAndEncoded(MONITOR_KEY, monitorUrl.toFullString());
                        }
                        if (logger.isInfoEnabled()) {
                            if (url.getParameter(REGISTER_KEY, true)) {
                                logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " +
                                        registryURL);
                            } else {
                                logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
                            }
                        }
 
                        // For providers, this is used to enable custom proxy to generate invoker
                        String proxy = url.getParameter(PROXY_KEY);
                        if (StringUtils.isNotEmpty(proxy)) {
                            registryURL = registryURL.addParameter(PROXY_KEY, proxy);
                        }
 
                        Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass,
                                registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
                        DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
 
                        Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);
                        exporters.add(exporter);
                    }
                } else {
                    if (logger.isInfoEnabled()) {
                        logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
                    }
                    Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, url);
                    DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
 
                    Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);
                    exporters.add(exporter);
                }
 
                MetadataUtils.publishServiceDefinition(url);
            }
        }
        this.urls.add(url);
    }

四、dubbo-admin查看并禁用服务

4.1 查询服务列表


4.2 禁用服务

4.2.1 dubbo-admin处理override节点

  • 删除disable=true的override服务并创建一个disable=true的override服务

4.2.2 service项目处理provider节点

  • service项目真正的监听器是 OverrideListener , 删除旧的provider节点,增加一个新的disable=true的provider节点

4.2.3 consumer项目刷新invoker列表

  • consumer项目真正的监听器是 RegistryDirectory.notify, 刷新本地的invoker列表, 共后续invokerInvocationHandler调用

4.3 启用服务

  • 和禁用服务逻辑差不多,此处略过

五、服务调用

标签:Dubbo,map,url,禁用,getName,启用,argument,KEY,method
From: https://www.cnblogs.com/qjwyss/p/17995133

相关文章

  • 怎么用CMD方式禁用windows defender
    运行禁用WindowsDefender的命令:在CMD中,您可以运行以下命令来编辑注册表,从而禁用WindowsDefender:REGADD"HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\WindowsDefender"/vDisableAntiSpyware/tREG_DWORD/d1/f请注意,这种方法可能在某些最新版本的Windows......
  • Dubbo 架构演进:从 RMI 到 Dubbo
    目录Dubbo架构演进:从RMI到Dubbo1.自定义RPC2.RMI架构2.1整体架构2.2RPC调用3.Dubbo架构3.1整体架构3.2RPC调用3.3服务治理4.总结时刻推荐阅读 谈谈你对Dubbo的认知?对于这个问题,你是怎么回答的呢?我们知道Dubbo是从RPC起家,......
  • MySQL如何快速禁用账户登入 & 如何复制/复用账户密码【转】
    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。作者:叶金荣文章来源:GreatSQL社区原创如何快速临时禁止某账户登入角色ROLES管理需要先激活关于授权的其他几点补充如何复制/复用账户密码1.快......
  • Win终端+WSL2 美化记录 上篇 启用毛玻璃
    微软还是太狗了,这么好看的毛玻璃效果藏着掖着,今天有幸看到,就有了本篇踩坑记录打开毛玻璃效果官方文档:https://learn.microsoft.com/zh-cn/windows/terminal/custom-terminal-gallery/frosted-glass-theme标签页毛玻璃设置-->外观-->开启Useacrylicmaterialintheta......
  • 如何为Azure Kubernetes Services启用Internal Loadbalancer
    如何为AzureKubernetesServices启用InternalLoadbalancer熟悉AzureKubernetesServices(AKS)的小伙伴都知道,默认情况下,当我们创建AzureKubernetesServices群集时,创建的都是Public的AKS群集,也就是可以提供Internet访问的AKS群集。PublicAKS群集会默认附带一个Public类型的Load......
  • 恭喜 Apache Dubbo 和 Nacos 荣获开放原子“2023年度生态开源项目”
    12月16日,以“一切为了开发者”为主题的开放原子开发者大会在江苏省无锡市开幕。江苏省工业和信息化厅厅长朱爱勋、中国开源软件推进联盟主席陆首群等领导和专家参加开幕式,工业和信息化部信息技术发展司副司长王威伟、江苏省工业和信息化厅副厅长池宇、无锡市人民政府副市长周文......
  • 恭喜 Apache Dubbo 和 Nacos 荣获开放原子“2023年度生态开源项目”
    12月16日,以“一切为了开发者”为主题的开放原子开发者大会在江苏省无锡市开幕。江苏省工业和信息化厅厅长朱爱勋、中国开源软件推进联盟主席陆首群等领导和专家参加开幕式,工业和信息化部信息技术发展司副司长王威伟、江苏省工业和信息化厅副厅长池宇、无锡市人民政府副市长周文......
  • 解决 Ant TreeSelect(树选择)组件可以使用键盘选中 disabled(已禁用)项的问题
    最近在使用AntDesignVue(V3.2.20)的TreeSelect组件时发现一个问题:tree-data中部分数据的disabled属性设置为了true,选项是“禁用”状态,无法通过鼠标点击选中,但是可以通过键盘↑↓键切换选项,按下Enter键选中。一开始还以为是bug,后来通过查阅文档和测试发现,该组件还......
  • CentOS7中禁用firewall,安装iptables
    ​ CentOS7中,firewalld是默认的防火墙管理工具,但若更熟悉或者更喜欢使用iptables,可以按照以下步骤禁用firewalld并安装iptables。 参考文档:CentOS7中禁用firewall,安装iptables-CJavaPy1、禁用firewall需要停止firewalld服务,并将其设置为在启动时不自动启动。1)检......
  • 中间件 ZK分布式专题与Dubbo微服务入门 4-15 acl的常用使用场景
    0课程地址https://coding.imooc.com/lesson/201.html#mid=12711 1重点关注1.1zk集群,主从节点,心跳机制(选举模式) 选举模式介绍1xx主节点(主人),yy和zz从节点(奴隶)2xx主节点挂掉了,yy和zz竞争当主人,结果zz成功上位,zz是主节点,yy是从节......