Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
jimchou800 opened this issue May 9, 2024 · 4 comments
Open

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

jimchou800 opened this issue May 9, 2024 · 4 comments

Comments

@jimchou800
Copy link

jimchou800 commented May 9, 2024

描述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_idapp2读到了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下隔离

截图

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

额外的细节和日志

  • 版本:
  • 错误日志
  • 配置:
  • 平台和操作系统
@nobodyiam
Copy link
Member

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

@jimchou800
Copy link
Author

确认了 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);    // ----------这里-------------- //
  }

@nobodyiam
Copy link
Member

下面 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); 
  }

@jimchou800
Copy link
Author

jimchou800 commented May 14, 2024

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

app:
  id: xxxxx

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants