apolloconfig / apollo

Apollo is a reliable configuration management system suitable for microservice configuration management scenarios.
https://www.apolloconfig.com
Apache License 2.0
29.17k stars 10.2k forks source link

SpringCloud项目中注解方式使用客户端导致Spring启动失败 #990

Open slankka opened 6 years ago

slankka commented 6 years ago

大神们好,我在SpringCloud(Spring core 4.2.6)中 使用Apollo Client,选用 使用Spring Annotation支持 这个方式启动失败,报错如下,还有一些Value注解的配置注入失败的信息没有贴出来。

[WARN] [17:26:00.336][DirectJDKLog][180]:The web application [ROOT] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.lang.Object.wait(Native Method)
 java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
 com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:43)
[ERROR] [17:26:00.342][SpringApplication][827]:Application startup failed

如果我用

@Component //加上注解
public class TestApolloAnnotationBean {
  @ApolloConfig
  private Config config; //inject config for namespace application
  @ApolloConfig("application")
  private Config anotherConfig; //inject config for namespace application
  @ApolloConfig("FX.apollo")
  private Config yetAnotherConfig; //inject config for namespace FX.apollo

  @Value("${batch:100}")
  private int batch;

删除

@Configuration
@EnableApolloConfig
public class AppConfig {
  @Bean
  public TestApolloAnnotationBean testApolloAnnotationBean() {
    return new TestApolloAnnotationBean();
  }
}

并且application配置文件指定 apollo.bootstrap.enabled: true则可以启动成功。

问题:

  1. 上文WIKI给出的注解配置是不是不支持SpringCloud?
  2. apollo.bootstrap.enabled 是否必须是true,不然启动完后,private Config config 这个值为null?
nobodyiam commented 6 years ago

@EnableApolloConfig的方式是支持绝大部分场景的,除非你的AppConfig没有被扫描到?

apollo.bootstrap.enabled的场景是针对Spring Boot的启动阶段的一些配置,比如@ConditionalOnProperty

slankka commented 6 years ago

我把报错的代码弄出来了,是最精简的环境,希望有人能够帮助我看一下是什么原因导致 https://github.com/slankka/Apollo-SpringCloudExample

slankka commented 6 years ago

已经解决。原因是项目在XML中配置了自定义的property-placeholder,会创建的PropertySourcesPlaceholderConfigurer,但Apollo Client在此之前抢先创建了这个Bean,但没能读取到这里的配置,导致给Bean填充Value的时候,失败了。详细内容请访问上面的链接。

nobodyiam commented 6 years ago

@slankka 非常感谢详细的分析。

由于Apollo的Spring使用方式依赖于PropertySourcesPlaceholderConfigurer,所以我们需要确保至少存在一个PropertySourcesPlaceholderConfigurer,这也是我们默认添加一个的原因。

我们后续看下是否可以把默认添加的这个PropertySourcesPlaceholderConfigurer的优先级调到最低,从而避免和用户的配置产生冲突。

slankka commented 6 years ago

Apollo 创建的PropertySourcesPlaceholderConfigurer中 ignoreUnresolvablePlaceholders 默认是true,导致只要没有配置值的,项目也不能启动成功。

nobodyiam commented 6 years ago

Apollo 创建的PropertySourcesPlaceholderConfigurer没有设置ignoreUnresolvablePlaceholders这个属性,看了下Spring代码里面默认值是false呀,org.springframework.beans.factory.config.PlaceholderConfigurerSupport#ignoreUnresolvablePlaceholders

slankka commented 6 years ago

不好意思,这个不是Apollo的问题。。另外优先级也不是Apollo的问题,只是需要说明一下,优先级默认刚好是int 最大值,都是最低的,需要用户自己提升优先级。

nobodyiam commented 6 years ago

恩,刚看了一下,确实order已经是最低了 - Ordered.LOWEST_PRECEDENCE

liu-hong commented 4 years ago

我现在用的1.2.1版本,我也遇到了这个问题,apollo在后面迭代中硬编码方式把PropertySourcesPlaceholderConfigurer优先级设为了0而不是注解中的最低,导致自定义的PropertySourcesPlaceholderConfigurer在后面加载,所以填充value报错。目前解决方法是把自定义的order设为-1

xiehanghang commented 4 years ago

现在解决了吗,我好想也遇到相同的问题

slankka commented 4 years ago

@xiehanghang 项目中,最多配置一个 PropertySourcesPlaceholderConfigurer。因此要么把自定义配置的文件按照Spring Boot的规范放置, 参见SpringBoot官方文档,文件名和路径都要按照规范; 要么自己加载Yaml配置文件, 另外,如果你一定要自己亲手加载配置文件,这里给出我当时的临时解决方案仅供参考