apache / dubbo

The java implementation of Apache Dubbo. An RPC and microservice framework.
https://dubbo.apache.org/
Apache License 2.0
40.39k stars 26.41k forks source link

ServiceDiscoveryRegistryDirectory中overrideQueryMap作用 #12337

Open jihanchen888 opened 1 year ago

jihanchen888 commented 1 year ago

在进行消费端应用级配置刷新时候,发现下面代码中overrideQueryMap中的条件一直没进入,最终每次都会被 new OverrideInstanceAddressURL(url) 中的配置 this.overrideParams = URLParam.parse("");刷新为空,导致配置中心配置变更了也没效果,看代码理解的overrideQueryMap应该是有用的,现在看好像没发现有值,这是为什么?

      if (referenceConfigurationListener != null) {
          providerUrl = overrideWithConfigurators(referenceConfigurationListener.getConfigurators(), providerUrl);
      } 

private InstanceAddressURL overrideWithConfigurators(List<Configurator> configurators, InstanceAddressURL url) {
        if (CollectionUtils.isNotEmpty(configurators)) {
            // wrap url
            OverrideInstanceAddressURL overrideInstanceAddressURL = new OverrideInstanceAddressURL(url);
            if (overrideQueryMap != null) {
                // override app-level configs
                overrideInstanceAddressURL = (OverrideInstanceAddressURL) overrideInstanceAddressURL.addParameters(overrideQueryMap);
            }
            for (Configurator configurator : configurators) {
                overrideInstanceAddressURL = (OverrideInstanceAddressURL) configurator.configure(overrideInstanceAddressURL);
            }
            return overrideInstanceAddressURL;
        }
        return url;
    }
AlbumenJ commented 1 year ago

overrideQueryMap 这个参数的作用应该是在 https://github.com/apache/dubbo/pull/9163 中删除的。

你说的配置刷新不生效具体是怎么配置的,覆盖了哪些参数,使用的 Dubbo 是什么版本。

jihanchen888 commented 1 year ago

dubbo版本:3.1.7 使用的官方框架内部的demo工程。提供者:dubbo-demo-spring-boot-provider 消费者:dubbo-demo-spring-boot-consumer (消费者改了下在main函数中循环调用doSayHello) 提供者配置: application.yml

dubbo:
  application:
    metadata-type: local
    name: dubbo-springboot-demo-provider
  protocol:
    name: dubbo
    port: -1
  registry:
    id: zk-registry
    address: zookeeper://127.0.0.1:2181
  config-center:
    address: nacos://127.0.0.1:8848
  metadata-report:
    address: zookeeper://127.0.0.1:2181

消费者配置: application.yml

dubbo:
  application:
    service-discovery:
      migration: FORCE_APPLICATION
    name: dubbo-springboot-demo-consumer
  protocol:
    name: dubbo
    port: -1
  registry:
    id: zk-registry
    address: zookeeper://127.0.0.1:2181
  config-center:
    address: nacos://127.0.0.1:8848
  metadata-report:
    address: zookeeper://127.0.0.1:2181

nacos中的配置项:

dataId: dubbo-springboot-demo-consumer.configurators   groupId:dubbo
configVersion: v3.1.7
scope: application
key: dubbo-springboot-demo-consumer
enabled: true
configs:
- addresses: ["0.0.0.0"]
  side: consumer
  parameters:
   timeout: 50001
   retries: 9
- addresses: ["0.0.0.0:20880"]
  side: provider
  parameters:
    actives: 10   

测了下基本的timeout参数也不支持动态刷新生效,是我使用方式有问题吗? 另外消费端我开启接口级订阅,对一些参数好像也没法做到动态刷新,比如cluster,retries

AlbumenJ commented 1 year ago

@chickenlj PTAL

chickenlj commented 1 year ago

@jihanchen888 建议使用 3.2.1 稳定版本。在3.2.x 版本中,路由规则进行了全面升级,支持了标签匹配等能力并修复了过往的一些问题

https://cn.dubbo.apache.org/zh-cn/overview/core-features/traffic/

https://cn.dubbo.apache.org/zh-cn/overview/tasks/traffic-management/timeout/

jihanchen888 commented 1 year ago

好的,了解了 我看了下最新版3.2.2 版本代码,在多机房注册中心时候,这边这个配置刷只会生效到一个机房吧? 第一个机房配置刷新后从新暴露设置到bounds中,后面机房循环进来更新时bounds中获取的exporterInvoker.getUrl()其实是之前更新过的,比较之后作为没有变更对应配置项就不会被更新。这样导致有时候调用的是配置生效的,有时候调用配置还是旧的

     public synchronized void doOverrideIfNecessary() {
            final Invoker<?> invoker;
            if (originInvoker instanceof InvokerDelegate) {
                invoker = ((InvokerDelegate<?>) originInvoker).getInvoker();
            } else {
                invoker = originInvoker;
            }
            //The origin invoker
            URL originUrl = RegistryProtocol.this.getProviderUrl(invoker);
            String key = getCacheKey(originInvoker);
            ExporterChangeableWrapper<?> exporter = bounds.get(key);
            if (exporter == null) {
                logger.warn(INTERNAL_ERROR, "unknown error in registry module", "", "error state, exporter should not be null", new IllegalStateException("error state, exporter should not be null"));
                return;
            }
            //The current, may have been merged many times
            Invoker<?> exporterInvoker = exporter.getInvoker();
            URL currentUrl = exporterInvoker == null ? null : exporterInvoker.getUrl();
            //Merged with this configuration
            URL newUrl = getConfiguredInvokerUrl(configurators, originUrl);
            newUrl = getConfiguredInvokerUrl(getProviderConfigurationListener(originUrl).getConfigurators(), newUrl);
            newUrl = getConfiguredInvokerUrl(serviceConfigurationListeners.get(originUrl.getServiceKey())
                .getConfigurators(), newUrl);
            if (!newUrl.equals(currentUrl)) {
                if (newUrl.getParameter(Constants.NEED_REEXPORT, true)) {
                    RegistryProtocol.this.reExport(originInvoker, newUrl);
                }
                logger.info("exported provider url changed, origin url: " + originUrl +
                    ", old export url: " + currentUrl + ", new export url: " + newUrl);
            }
        }
AlbumenJ commented 1 year ago

好的,了解了 我看了下最新版3.2.2 版本代码,在多机房注册中心时候,这边这个配置刷只会生效到一个机房吧? 第一个机房配置刷新后从新暴露设置到bounds中,后面机房循环进来更新时bounds中获取的exporterInvoker.getUrl()其实是之前更新过的,比较之后作为没有变更对应配置项就不会被更新。这样导致有时候调用的是配置生效的,有时候调用配置还是旧的

     public synchronized void doOverrideIfNecessary() {
            final Invoker<?> invoker;
            if (originInvoker instanceof InvokerDelegate) {
                invoker = ((InvokerDelegate<?>) originInvoker).getInvoker();
            } else {
                invoker = originInvoker;
            }
            //The origin invoker
            URL originUrl = RegistryProtocol.this.getProviderUrl(invoker);
            String key = getCacheKey(originInvoker);
            ExporterChangeableWrapper<?> exporter = bounds.get(key);
            if (exporter == null) {
                logger.warn(INTERNAL_ERROR, "unknown error in registry module", "", "error state, exporter should not be null", new IllegalStateException("error state, exporter should not be null"));
                return;
            }
            //The current, may have been merged many times
            Invoker<?> exporterInvoker = exporter.getInvoker();
            URL currentUrl = exporterInvoker == null ? null : exporterInvoker.getUrl();
            //Merged with this configuration
            URL newUrl = getConfiguredInvokerUrl(configurators, originUrl);
            newUrl = getConfiguredInvokerUrl(getProviderConfigurationListener(originUrl).getConfigurators(), newUrl);
            newUrl = getConfiguredInvokerUrl(serviceConfigurationListeners.get(originUrl.getServiceKey())
                .getConfigurators(), newUrl);
            if (!newUrl.equals(currentUrl)) {
                if (newUrl.getParameter(Constants.NEED_REEXPORT, true)) {
                    RegistryProtocol.this.reExport(originInvoker, newUrl);
                }
                logger.info("exported provider url changed, origin url: " + originUrl +
                    ", old export url: " + currentUrl + ", new export url: " + newUrl);
            }
        }

这个配置在多注册中心的时候确实是有问题的,可以帮提个 issue 或者尝试提个 PR 修复下