Skip to content

Dubbo 2.7.5 problems summary #5777

@itfinally

Description

@itfinally
  • I have searched the issues of this repository and believe that this is not a duplicate.
  • I have checked the FAQ of this repository and believe that this is not a duplicate.

All problem already resolve by Dubbo SPI on my framework, but I think I should share those problems and the reason why those problems come up.

Please Dubbo team fix those issue for good.

Environment

  • Dubbo version: Dubbo 2.7.5
  • Operating System version: MacOS
  • Java version: Oracle JDK 8

Finally I back to the Vertion 2.7.4.1, And This is all issue of the Dubbo 2.7.5 I found:

  • Failure due to the Dubbo starting early. This is my environment:

    • Dubbo 2.7.5 + Nacos 1.1.4
    • Use Dynamic Config Center
    • Spring boot 2.1.9
    • Use YAML Config

    In this case, the Dubbo will be startup before the ConfigCenterConfig inject into DubboBootstrap, it make Dubbo use default config and starting failure. And the reason of the Dubbo startup is Spring framework scan Dubbo Service Interface and initial it, and the Dubbo Service Interface active the Dubbo framework. the Dubbo framework not even get the ConfigCenterConfig at that time.

    After reading the Dubbo source code, I found some key code in the class DubboBootstrap, method name startConfigCenter, line 560.

    // Get the class "ConfigCenterConfig"
    Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
    
    if (CollectionUtils.isNotEmpty(configCenters)) {
      CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration();
      for (ConfigCenterConfig configCenter : configCenters) {
        configCenter.refresh();
        ConfigValidationUtils.validateConfigCenterConfig(configCenter);
      
        // The method "prepareEnvironment" get all dubbo config from remote server
        compositeDynamicConfiguration.addConfiguration(prepareEnvironment(configCenter));
      }
      environment.setDynamicConfiguration(compositeDynamicConfiguration);
    }
    configManager.refreshAll();

    And this is the code I use to fix that problem( This code can not fix the problem in some case because it still depend on the order of the Bean initialize in Spring framework, that is the reason why I specified name at @Configuration. for the @DependOn ):

    @Order(-1)
    @AllArgsConstructor
    @Configuration("apacheDubboBootstrap")
    @ConditionalOnClass(name = "org.apache.dubbo.config.ConfigCenterConfig")
    public static class ApacheDubboBootstrap {
    
      private final DynamicConfigProperties properties;
        
      @PostConstruct
      public void init() {
        // 在 Spring boot 环境下由于 Dubbo 接口的代理类创建间接触发了 Dubbo 框架流程
        // 这一行代码是为了解决启动优先级的问题, 在触发 Dubbo 框架流程之前注入动态配置中心配置
        // 而依赖 Spring boot 进行注入有可能会因为 Dubbo 先启动而不知道存在配置中心导致启动失败
        DubboBootstrap.getInstance().configCenter(properties.ofConfigCenterConfig());
      }
    }
  • Not friendly with the YAML config

    For the history reason, the Dubbo framework use XML as config foramt at early, then Properties come up. And now I found that the Dubbo not identify and not inject the YAML config, only XML and Properties can.

    For example, This is the qos server config in YAML:
    # Wrong config
    # This config ( just qos-enable ) problem seem like fixed in Dubbo 2.7.5 ? But I haven't verified yet
    dubbo:
      application:
        qos-enable: true
        
    # Correct config
    dubbo:
      application:
        qos.enable: true

    If you run Dubbo as debug mode and put some breakpoint in the class ApplicationConfig, you can see the method setQosEnable only be called when you write qos.enable . And what about qos-enable ? Just nothing happen.

    And other example, The ConfigCenterConfig:
    dubbo:
      config-center:
        address: nacos://xxxx
        config-file: xxxxxx
        group: xxxxxx
        namespace: xxxxxx

    Only address is effective in those configs( The method setAddress has been called ) and other config still keep that default value( Nothing happen on the setter of those property ). So that I have to write my configuration and use it config Dubbo:

    public class DynamicConfigProperties {
      public static final String PREFIX = "dubbo.config-server";
    
        /**
         * Nacos 服务 Ip 地址
         */
        private String serverAddr;
      
      // some property...
      
      public org.apache.dubbo.config.ConfigCenterConfig ofConfigCenterConfig() {
        org.apache.dubbo.config.ConfigCenterConfig config = new ConfigCenterConfig();
    
        Map<String, String> parameters = new HashMap<>(4);
    
        setParameter(parameters, PropertyKeyConst.ACCESS_KEY, accessKey);
        setParameter(parameters, PropertyKeyConst.SECRET_KEY, secretKey);
        setParameter(parameters, PropertyKeyConst.ENDPOINT, endpoint);
    
        config.setParameters(parameters);
    
        config.setHighestPriority(allowOverride);
        config.setNamespace(namespace);
        config.setAddress(serverAddr);
        config.setConfigFile(dataId);
        config.setCheck(abortOnFail);
        config.setTimeout(timeout);
        config.setGroup(group);
    
        return config;
      }
    }
    The last example, let see the DubboBootstrap, method prepareEnvironment, line 828 & 829.
    DynamicConfiguration dynamicConfiguration = getDynamicConfiguration(configCenter.toUrl());
    
    // Get config from remote server.
    String configContent = dynamicConfiguration.getProperties(configCenter.getConfigFile(), configCenter.getGroup());
    
    String appGroup = getApplication().getName();
    String appConfigContent = null;
    if (isNotEmpty(appGroup)) {
        appConfigContent = dynamicConfiguration.getProperties
                (isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(),
                        appGroup
                );
    }
    try {
        environment.setConfigCenterFirst(configCenter.isHighestPriority());
      
        // It force all remote config must use "properties" format.
        environment.updateExternalConfigurationMap(parseProperties(configContent));
        environment.updateAppExternalConfigurationMap(parseProperties(appConfigContent));
      
      
    } catch (IOException e) {
        throw new IllegalStateException("Failed to parse configurations from Config Center.", e);
    }

    Because the method parseProperties, I have to create my own protocol banacos and BanacosDynamicConfiguration, the goal is parse yaml and tranform to properties format.

    It should be add a property name format( or file-extension like nacos client ? ) to decide what parser should be Dubbo use, rather than write those dead code.

  • Metadata server not effective, and the ServiceNameMapping write meta data anywhere

    The reason of meta server not effective is same with my first issue "Failure due to the Dubbo starting early". Let see DubboBootstrap again, the method startMetadataReport:

    ApplicationConfig applicationConfig = getApplication();
    
    String metadataType = applicationConfig.getMetadataType();
    // FIXME, multiple metadata config support.
    Collection<MetadataReportConfig> metadataReportConfigs = configManager.getMetadataConfigs();
    if (CollectionUtils.isEmpty(metadataReportConfigs)) {
      if (REMOTE_METADATA_STORAGE_TYPE.equals(metadataType)) {
        throw new IllegalStateException("No MetadataConfig found, you must specify the remote Metadata Center address when 'metadata=remote' is enabled.");
      }
      return;
    }
    MetadataReportConfig metadataReportConfig = metadataReportConfigs.iterator().next();
    ConfigValidationUtils.validateMetadataConfig(metadataReportConfig);
    if (!metadataReportConfig.isValid()) {
      return;
    }
    
    MetadataReportInstance.init(metadataReportConfig.toUrl());

    Is it familiar ? Dubbo activate too soon, even before any config injected, that is the reason why some functions is not work on Dubbo 2.7.5 . We should pay attention to the Bean initialize, especially startup Dubbo under Spring framrwork.

    And this is the last issue for this article, the class DynamicConfigurationServiceNameMapping push metadata to anywhere:

    @Override
    public void map(String serviceInterface, String group, String version, String protocol) {
    
      if (IGNORED_SERVICE_INTERFACES.contains(serviceInterface)) {
        return;
      }
    
      // The value of variable 'dynamicConfiguration' is CompositeDynamicConfiguration
      DynamicConfiguration dynamicConfiguration = DynamicConfiguration.getDynamicConfiguration();
    }

    The javadoc of the class CompositeDynamicConfiguration is support multiple config center, simply iterating each concrete config center. It mean this class will push metadata to any config center we configed.

    In my opinion, those "metadata" should push to metadata server rather than config server. Now every I startup Dubbo service as provider, my config server always fill all data that useless in my view. Just a mess on my config server If I startup all Dubbo service.

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions