apollo-java icon indicating copy to clipboard operation
apollo-java copied to clipboard

tomcat下多应用System.getProperty("app.id")共享

Open jimchou800 opened this issue 1 year ago • 4 comments

描述bug 1、有两个比较老的SpringMvc项目,部署在同一个tomcat是tomcat 7.0.93 , 每个项目classpath:META-INF/app.properties配置的app.id不同。

2、在启动时,只有一个应用能启动成功,另一个应用有日志提示:App ID is set to xxx by app.id property from System Property, 说明应用2是从 System.getProperty("app_id")拿到了前一个应用调System.setProperty("app_id", app)设置的值

3、写了两个简单的webapp,放在同一个tomcat下,经过验证发现,System.getProperty() 在多个tomcat webapp下是共享的,即一个app调 System.setProperty("app_id", app)后,另一个项目能拿到相同的值,导致另外一个app没有正确拿到app.id参数

问题在这里,app1启动后,会调System.setProperty设置自身的app_id;app2读到了app1写入的app_id
com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java

  private void fillSystemPropertyFromEnvironment(ConfigurableEnvironment environment, String propertyName) {
    if (System.getProperty(propertyName) != null) {
      return;
    }

    String propertyValue = environment.getProperty(propertyName);

    if (Strings.isNullOrEmpty(propertyValue)) {
      return;
    }

    System.setProperty(propertyName, propertyValue);  ------ **app1在这里设置了自身的app_id=app1**
  }
com.ctrip.framework.foundation.internals.provider.DefaultApplicationProvider

  private void initAppId() {
    // 1. Get app.id from System Property
    m_appId = System.getProperty("app.id"); ----- **app在这里拿到了先启动项目设置的app.id,即app1(预期是app2)**
    if (!Utils.isBlank(m_appId)) {
      m_appId = m_appId.trim();
      logger.info("App ID is set to {} by app.id property from System Property", m_appId);
      return;
    }

    //2. Try to get app id from OS environment variable
    m_appId = System.getenv("APP_ID");
    if (!Utils.isBlank(m_appId)) {
      m_appId = m_appId.trim();
      logger.info("App ID is set to {} by APP_ID property from OS environment variable", m_appId);
      return;
    }

简洁明了地描述一下bug

在tomcat下,多个应用 System.setProperty("app.id") 、System.getProperty("app.id") 全局共享

期望

tomcat下隔离

截图

如果可以,附上截图来描述你的问题

额外的细节和日志

  • 版本:
  • 错误日志
  • 配置:
  • 平台和操作系统

jimchou800 avatar May 09 '24 09:05 jimchou800

检查下是否在 application.properties 里面设置 app.id 了,如果只是在 META-INF/app.properties 中设置 app.id 的话是不会更新到 system properties 里的

nobodyiam avatar May 11 '24 01:05 nobodyiam

确认了 application.properties 中没有app.id,所使用的apollo-client版本 1.8.0。

问题出在这个类:com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer

  @Override
  public void postProcessEnvironment(ConfigurableEnvironment configurableEnvironment, SpringApplication springApplication) {

    // should always initialize system properties like app.id in the first place
    initializeSystemProperty(configurableEnvironment);

    Boolean eagerLoadEnabled = configurableEnvironment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_EAGER_LOAD_ENABLED, Boolean.class, false);

    //EnvironmentPostProcessor should not be triggered if you don't want Apollo Loading before Logging System Initialization
    if (!eagerLoadEnabled) {
      return;
    }

    Boolean bootstrapEnabled = configurableEnvironment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED, Boolean.class, false);

    if (bootstrapEnabled) {
      initialize(configurableEnvironment);
    }
  }

  void initializeSystemProperty(ConfigurableEnvironment environment) {
    for (String propertyName : APOLLO_SYSTEM_PROPERTIES) {
      fillSystemPropertyFromEnvironment(environment, propertyName);
    }
  }

  private void fillSystemPropertyFromEnvironment(ConfigurableEnvironment environment, String propertyName) {
    if (System.getProperty(propertyName) != null) {
      return;
    }

    String propertyValue = environment.getProperty(propertyName);

    if (Strings.isNullOrEmpty(propertyValue)) {
      return;
    }
    
    System.setProperty(propertyName, propertyValue);    // ----------这里-------------- //
  }


jimchou800 avatar May 11 '24 03:05 jimchou800

下面 propertyValue 读到的应该是空,所以不会执行 System.setProperty 操作。如果读到不为空,可以看下 environment 里面是哪里配置了 app.id 属性

private void fillSystemPropertyFromEnvironment(ConfigurableEnvironment environment, String propertyName) {
    if (System.getProperty(propertyName) != null) {
      return;
    }

    String propertyValue = environment.getProperty(propertyName); // ----------这里读到的应该是空-------------- //

    if (Strings.isNullOrEmpty(propertyValue)) {
      return;
    }
    
    System.setProperty(propertyName, propertyValue); 
  }

nobodyiam avatar May 12 '24 06:05 nobodyiam

经过排查在一个spring配置文件 application-xxx.yml 中确实是有这样的配置。此issue,可以关闭了,但个人感觉这是一个坑,建议优化,最后,感谢大佬的解答。

app:
  id: xxxxx

apollo:
  bootstrap:
    enabled: true
    eagerLoad:
      enabled: true
    namespaces: application

jimchou800 avatar May 14 '24 03:05 jimchou800

This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in 7 days unless it is tagged "help wanted" or other activity occurs. Thank you for your contributions.

stale[bot] avatar Jun 13 '24 21:06 stale[bot]

This issue has been automatically closed because it has not had activity in the last 7 days. If this issue is still valid, please ping a maintainer and ask them to label it as "help wanted". Thank you for your contributions.

stale[bot] avatar Jun 23 '24 15:06 stale[bot]