解决Dubbo 2.7.3版本使用ConfigCenterConfig集成Apollo No Provider found的问题

匿名 (未验证) 提交于 2019-12-02 23:56:01

Dubbo 2.7.3支持配置中心外部化配置, 因此只需要定义一个ConfigCenterConfig的Bean。

@EnableDubbo(scanBasePackages = {"com.slankka.cloud.dubbo"}) @Configuration public class DubboConfig {     @Bean     public ConfigCenterConfig configCenterConfig() {         ConfigCenterConfig configCenterConfig = new ConfigCenterConfig();         configCenterConfig.setAddress("apollo.xxxxx.com:8080");         configCenterConfig.setProtocol("apollo");         configCenterConfig.setNamespace("dubbo");         configCenterConfig.setGroup(null);         return configCenterConfig;     } }

问题:

  1. Apollo 找不到 meta。
  2. Dubbo 找不到 provider
  1. Apollo 找不到meta,Apollo的jar 的apollo-core的配置文件明明声明了PRO.meta="apollo.xxxxx.com:8080"。这个问题出现在
apollo.bootstrap.enabled = false

如果要坚持这样配置,需要增加

apollo.meta=apollo.xxxxx.com:8080
  1. Dubbo 找不到Provider,仔细看日志 Interface: com.xxx.xxx.service,如果后面没有跟着版本号例如: 1.2.0,则说明版本没有定义。
    问题是因为定义了占位符,而Dubbo启动的时候,创建ReferenceBean的类是个BeanPostProcessor,启动比较早,而apollo.bootstrap.enabled=false。
    则Dubbo创建这个IRExecutionService对应的Bean类的时候,找不到version,但是他catch吃掉异常了。等于没有配置version。
apollo.bootstrap.enabled = false  @Reference(version = "${job.service.version}", retries = 0, lazy = true) private IRExecutionService executionService;

则原因是Dubbo不能从ConfigCenterConfig读取版本配置,或者太迟了,如果要解决很简单 ,但是太依赖Apollo提前初始化开关。

package io.github.slankka.dubbo-apollo.server.config;  import org.apache.dubbo.common.URL; import org.apache.dubbo.common.config.Configuration; import org.apache.dubbo.common.config.Environment; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.ConfigCenterConfig; import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; import org.apache.dubbo.configcenter.DynamicConfiguration; import org.apache.dubbo.configcenter.DynamicConfigurationFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.InjectionMetadata; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver; import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.PropertySource; import org.springframework.stereotype.Component;  import java.io.IOException; import java.util.ArrayList; import java.util.List;  import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties;  /**  * Project: dubbo-apollo  *  * @author slankka on 2019/8/29.  */ @ConditionalOnProperty(name = "apollo.bootstrap.enabled", havingValue = "false", matchIfMissing = true) @Component(value = ReferenceAnnotationBeanPostProcessor.BEAN_NAME) public class ReferencedAnnotationPatch extends ReferenceAnnotationBeanPostProcessor {      private ApplicationContext myContext;      @Override     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {         myContext = applicationContext;         super.setApplicationContext(applicationContext);     }      @Override     protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName,                                        Class<?> injectedType,                                        InjectionMetadata.InjectedElement injectedElement) throws Exception {         eagerInitConfigCenter();         Configuration configuration = Environment.getInstance().getConfiguration();          List<PropertySource<?>> propertySources = new ArrayList<>();         propertySources.add(new PropertySource<Configuration>("dubboConfigCenter", configuration) {             @Override             public Object getProperty(String name) {                 return configuration.getProperty(name);             }         });         PropertySourcesPlaceholdersResolver propertySourcesPlaceholdersResolver = new PropertySourcesPlaceholdersResolver(propertySources);          for (String attribute : attributes.keySet()) {             Object stringAttr = attributes.get(attribute);             if (stringAttr instanceof String) {                 Object value = propertySourcesPlaceholdersResolver.resolvePlaceholders(attributes.getString(attribute));                 attributes.put(attribute, value);             }         }          return super.doGetInjectedBean(attributes, bean, beanName, injectedType, injectedElement);     }      private void eagerInitConfigCenter() {         ConfigCenterConfig configCenter = myContext.getBean(ConfigCenterConfig.class);         if (configCenter.isValid()) {             if (configCenter.checkOrUpdateInited()) {                 configCenter.refresh();                  URL url = configCenter.toUrl();                 DynamicConfigurationFactory factories = ExtensionLoader                         .getExtensionLoader(DynamicConfigurationFactory.class)                         .getExtension(url.getProtocol());                 DynamicConfiguration dynamicConfiguration = factories.getDynamicConfiguration(url);                 String configContent = dynamicConfiguration.getProperties(configCenter.getConfigFile(), configCenter.getGroup());                  ApplicationConfig application = myContext.getBean(ApplicationConfig.class);                 String appGroup = application.getName();                 String appConfigContent = null;                 if (StringUtils.isNotEmpty(appGroup)) {                     appConfigContent = dynamicConfiguration.getProperties                             (StringUtils.isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(),                                     appGroup                             );                 }                 try {                     Environment.getInstance().setConfigCenterFirst(configCenter.isHighestPriority());                     Environment.getInstance().updateExternalConfigurationMap(parseProperties(configContent));                     Environment.getInstance().updateAppExternalConfigurationMap(parseProperties(appConfigContent));                 } catch (IOException e) {                     throw new IllegalStateException("Failed to parse configurations from Config Center.", e);                 }             }         }     } }

则能纠正Dubbo 的ReferenceAnnotationBeanPostProcessor 行为,因为这个时候,已经有ConfigCenterConfig这个Bean了,所以让ConfigCenter提前启动,从而使得@Reference注解的占位符能够被解析。
注意,这个占位符是配置在Namespace("dubbo");内的。

Dubbo 会默认读取 dubbo这个 Apollo的namespace,如果用自定义的namespace,他也会读取,因为不存在而启动减慢,所以为了加快启动速度,建议创建Apollo的 一个空dubbo的namespace。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!