Apollo、RocketMQ加载顺序问题

Apollo、RocketMQ加载顺序问题_第1张图片

 

 

在SpringCloudAlibaba框架中,因Nacos配置中心管理权限过于简单,决定用Apollo代替Nacos配置中心,但在启动时,Nacos、Redis等配置读取正常,RocketMQ由于启动过早,无法从Apollo读取自己的服务地址配置。

报错如下:

Error processing condition on RocketMQAutoConfiguration.

Apollo、RocketMQ加载顺序问题_第2张图片

针对此问题,进行以下3个方向的尝试,最开始觉得如果其他组件能正常读取Apollo配置,那应该是RocketMQ的问题,想办法降低它的加载顺序。最终发现不太现实,在RocketMQ社区也未找到相关问题。

尝试1.让rocketmq-spring-boot中的RocketMQAutoConfiguration延迟加载-失败

最起码要晚于ApolloAutoConfiguration。

Apollo、RocketMQ加载顺序问题_第3张图片

如下方案失败:

/**
 * 试图让RocketMQAutoConfiguration在ApolloAutoConfiguration之后加载
 */
@Configuration
@AutoConfigureBefore(RocketMQAutoConfiguration.class)
public class OrderConfiguration {
    @Bean
    @ConditionalOnMissingBean(ApolloAutoConfiguration.class)
    public ApolloAutoConfiguration apolloAutoConfiguration() {
        return new ApolloAutoConfiguration();
    }
}

尝试2:开启全局懒加载,并排除Apollo-失败

Apollo、RocketMQ加载顺序问题_第4张图片

尝试3:修改EnableApolloConfig order属性-失败

在启动类修改EnableApolloConfig order属性,还是报同样的错误。

Apollo、RocketMQ加载顺序问题_第5张图片

@EnableApolloConfig(order = Integer.MIN VALUE)

解决方案:设置apollo更早阶段注入

直到忙活几个小时后,发现Apollo官方已经提供了容Apollo更早注入的方法,解决方法:

@SpringBootApplication
// 允许使用Feign客户端发送请求
@EnableFeignClients
// 指定要扫描的Mapper类的包的路径
@MapperScan("com.**.dao")
@EnableRedis
@EnableApolloConfig
// 扫描加载Filter
@ServletComponentScan
public class Application {
    public static void main(String[] args) {
        // 启用apollo配置开关 在应用启动阶段是否向Spring容器注入被托管的properties文件配置信息。
        System.setProperty("apollo.bootstrap.enabled","true");
        // 将Apollo配置加载提到初始化日志系统之前。
        System.setProperty("apollo.bootstrap.eagerLoad.enabled","true");

        SpringApplication.run(Application.class, args);
    }
}

还有另一种方式:

Apollo官方文档

Apollo

Spring Boot除了支持上述两种集成方式以外,还支持通过application.properties/bootstrap.properties来配置,该方式能使配置在更早的阶段注入,比如使用@ConditionalOnProperty的场景或者是有一些spring-boot-starter在启动阶段就需要读取配置做一些事情(如dubbo-spring-boot-project),所以对于Spring Boot环境建议通过以下方式来接入Apollo(需要0.10.0及以上版本)。
从1.2.0版本开始,如果希望把日志相关的配置(如logging.level.root=info或logback-spring.xml中的参数)也放在Apollo管理,那么可以额外配置apollo.bootstrap.eagerLoad.enabled=true来使Apollo的加载顺序放到日志系统加载之前,不过这会导致Apollo的启动过程无法通过日志的方式输出(因为执行Apollo加载的时候,日志系统压根没有准备好呢!所以在Apollo代码中使用Slf4j的日志输出便没有任何内容),更多信息可以参考PR 1614。参考配置示例如下:
# will inject 'application' namespace in bootstrap phase
apollo.bootstrap.enabled = true
# put apollo initialization before logging system initialization
apollo.bootstrap.eagerLoad.enabled=true

        因为搜索方向不对浪费了几个小时,一开始一直在搜索如何让RocketMQ加载晚于Apollo,重点在调整两者加载顺序上,后来又在研究RocketMQAutoConfiguration的加载原理,尝试各种方法让RMQ延迟加载,最后随便搜了一下Apollo加载顺序,答案其实很多,在解决问题时还是要多扩散一下思路。


 

你可能感兴趣的:(Java,java,spring,cloud)