zoukankan      html  css  js  c++  java
  • 解决Dubbo 2.7.3版本使用ConfigCenterConfig集成Apollo No Provider found的问题

    Dubbo 2.7.3 集成Apollo

    问题描述

    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
    

    更新:此问题还有更深入的分析Apollo报错找不到apollo.meta的问题解决方案

    2. 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提前初始化开关。

    如果坚持要apollo.bootstrap.enabled = false,强制使用Dubbo自行处理这个变量的解析怎么办?

    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。

  • 相关阅读:
    Flink延时监控
    FLink全链路时延—测量方式
    Linux搭建SFTP服务器
    Red Hat:USING AMQ STREAMS WITH MIRRORMAKER 2.0
    idea 搭建运行kafka 源码
    Kafka Connect Concepts
    Java IPv6相关属性preferIPv4Stack、preferIPv6Addresses介绍
    如何确定Flink反压的根源?How to identify the source of backpressure?
    如何成为 Apache 项目的 Committer
    Apache Kafka KIP 介绍
  • 原文地址:https://www.cnblogs.com/slankka/p/11431324.html
Copyright © 2011-2022 走看看