Apollo使用篇 - Apollo客户端的使用

凌意
2023-12-01

准备工作

环境要求

Java 1.8+

Guava 20.0+

必选设置

AppId

AppId 是应用的身份信息,是从服务端获取配置的一个重要信息。

有如下几种方式设置,按照优先级从高到低分别为:

1、System Property

Apollo 0.7.0+ 支持通过 System Property 传入 app.id 信息。

-Dapp.id=YOUR-APP-ID

2、System Environment

Apollo 1.4.0+ 支持通过操作系统的 System Envinronment APP_ID 来传入 app.id 信息。

APP_ID=YOUR-APP-ID

3、application.properties

Apollo 1.0.0+ 支持通过 Spring Boot 的 application.properties 文件配置。

该配置方式不适用于多个 war 包部署在同一个 tomcat 的使用场景。

app.id=YOUR-APP-ID

4、app.properties

在 classpath:/META-INF/app.properties 文件中指定配置。

app.id=YOUR-APP-ID

Apollo Meta Server

Apollo Meta Server 的地址。按照优先级从高到低分别为:

1、System Property

可以通过 Java 的 System Property 指定。

-Dapollo.meta=http://config-service-url

如果是运行 jar 文件,可以通过如下格式指定。

java -Dapollo.meta=http://config-service-url -jar xxx.jar

也可以通过程序指定。

System.setProperty("apollo.meta", "http://config-service-url");

2、application.properties 或者 bootstrap.properties

该配置方式不适用于多个 war 包部署在同一个 tomcat 的使用场景。

apollo.meta=http://config-service-url

3、System Environment

通过操作系统的 System Environment

APOLLO_META=http://config-service-url

4、server.properties

对于 Mac/Linux,默认文件位置为:/opt/settings/server.properties

对于 Windows,默认文件位置为:C:\opt\settings\server.properties

apollo.meta=http://config-service-url

5、app.properties

classpath:/META-INF/app.properties 文件中指定。

apollo.meta=http://config-service-url

6、System Property ${env}_meta

-Ddev_meta=http://config-service-url

7、System Environment ${ENV}_META

DEV_META=http://config-service-url

8、apollo-env.properties

程序的 classpath 下,或者 Spring Boot 应用的 config 目录下。

dev.meta=http://1.1.1.1:8080
fat.meta=http://apollo.fat.xxx.com
uat.meta=http://apollo.uat.xxx.com
pro.meta=http://apollo.xxx.com

本地缓存路径

Apollo 客户端会把从服务端获取到的配置在本地文件系统缓存一份,用于在遇到服务不可用,或者网络不通的时候,依然能够从本地恢复配置,不影响应用正常使用。

本地缓存的默认目录如下:

  • Mac/Linux: /opt/data/{appId}/config-cache
  • Windows: C:\opt\data\{appId}\config-cache

本地配置文件会以下面的文件名格式放置于本地缓存路径下:

{appId}+{cluster}+{namespace}.properties

1.0.0 版本支持如下方式自定义缓存路径,按照优先级从高到低分别为:

1、System Property

  • 可以通过 Java 的 System Property apollo.cache-dir (1.9.0 +)、apollo.cacheDir(1.9.0 之前)来指定。

  • 在Java程序启动脚本中,可以指定 -Dapollo.cache-dir=/opt/data/some-cache-dir (1.9.0 +) 或者 apollo.cacheDir=/opt/data/some-cache-dir (1.9.0 之前)

  • 如果是运行 jar 文件,需要注意格式是 java -Dapollo.cache-dir=/opt/data/some-cache-dir -jar xxx.jar(1.9.0 +) 或者 java -Dapollo.cacheDir=/opt/data/some-cache-dir -jar xxx.jar(1.9.0 之前)

  • 也可以通过程序指定,如 System.setProperty("apollo.cache-dir", "/opt/data/some-cache-dir");(1.9.0 +) 或者 System.setProperty("apollo.cacheDir", "/opt/data/some-cache-dir"); (1.9.0 之前)

2、application.properties、bootstrap.properties

指定 apollo.cache-dir=/opt/data/some-cache-dir (1.9.0 +) 或者 apollo.cacheDir=/opt/data/some-cache-dir (1.9.0 之前)

3、System Environment

APOLLO_CACHE_DIR (1.9.0 +) 或者 APOLLO_CACHEDIR(1.9.0 之前)

4、server.properties

指定 apollo.cache-dir=/opt/data/some-cache-dir (1.9.0 +) 或者 apollo.cacheDir=/opt/data/some-cache-dir (1.9.0 之前)

  • 对于Mac/Linux,默认文件位置为 /opt/settings/server.properties
  • 对于Windows,默认文件位置为 C:\opt\settings\server.properties

可选设置

Environment

目前 env 支持 DEV、FAT、UAT、PRO 几个值。

可以通过如下三种方式进行配置。

1、System Property

  • 可以通过 Java 的 System Property env 来指定环境。
  • 在 Java 程序启动脚本中,可以指定 -Denv=YOUR-ENVIRONMENT
    • 如果是运行 jar 文件,需要注意格式是 java -Denv=YOUR-ENVINRONMENT -jar xxx.jar
  • 注意 key 是小写。

2、System Environment

  • 可以通过操作系统的 System Environment ENV 来指定。
  • 注意 key 为 大写。

3、通过配置文件

  • 对于Mac/Linux,默认文件位置为 /opt/settings/server.properties
  • 对于Windows,默认文件位置为 C:\opt\settings\server.properties

Cluster

Apollo 支持配置按照集群划分,也就是对于一个 appId 和一个环境,对于不同集群可以有不同的配置。

1.0.0 版本开始支持以下方式配置,按照优先级从高到低分别为:

1、 System Property 指定 apollo.cluster

  • 可以通过 Java 的 System Property apollo.cluster来指定
  • 在 Java 程序启动脚本中,可以指定 -Dapollo.cluster=SomeCluster
    • 如果是运行jar文件,需要注意格式是 java -Dapollo.cluster=SomeCluster -jar xxx.jar
  • 也可以通过程序指定,如 System.setProperty("apollo.cluster", "SomeCluster");

2、application.properties、bootstrap.properties 文件中指定 apollo.cluster=SomeCluster

3、System Property 指定 idc

  • 可以通过 Java 的 System Property idc 来指定环境
  • 在 Java 程序启动脚本中,可以指定 -Didc=xxx
    • 如果是运行 jar 文件,需要注意格式是 java -Didc=xxx -jar xxx.jar
  • 注意 key 为全小写

4、System Environment 指定 idc

  • 还可以通过操作系统的 System Environment IDC 来指定
    • 注意 key 为全大写

5、server.properties

  • 可以在 server.properties 配置文件中指定 idc=xxx
  • 对于Mac/Linux,默认文件位置为 /opt/settings/server.properties
  • 对于Windows,默认文件位置为 C:\opt\settings\server.properties

Cluster Precedence(集群顺序)

1、如果 apollo.cluster 和idc 同时指定:

  • 我们会首先尝试从 apollo.cluster 指定的集群加载配置
  • 如果没找到任何配置,会尝试从 idc 指定的集群加载配置
  • 如果还是没找到,会从默认的集群(default)加载

2、如果只指定了 apollo.cluster:

  • 我们会首先尝试从 apollo.cluster 指定的集群加载配置
  • 如果没找到,会从默认的集群(default)加载

3、如果只指定了 idc:

  • 我们会首先尝试从 idc 指定的集群加载配置
  • 如果没找到,会从默认的集群(default)加载

4、如果 apollo.cluster 和 idc 都没有指定:

  • 我们会从默认的集群(default)加载配置

设置内存中的配置项是否保持和页面中的顺序一致

默认情况下,apollo client 内存中的配置存放在 Properties 中,不会刻意保持和页面上看到的顺序一致,对绝大部分的场景是没有影响的。不过有些场景会强依赖配置项的顺序(如 Spring Cloud Zuul 的路由规则),针对这种情况,可以开启 OrderedProperties 特性来使得内存中的配置顺序和页面上看到的一致。

配置方式按照优先级从高到低分别为:

1、System Property

  • 可以通过Java的System Property apollo.property.order.enable来指定
  • 在Java程序启动脚本中,指定 java -Dapollo.property.order.enable=true -jar xxx.jar
  • 也可以通过程序指定,如System.setProperty("apollo.property.order.enable", "true");

2、application.properties 或者 bootstrap.properties 文件中指定 apollo.property.order.enable=true

3、app.properties

  • 可以在classpath:/META-INF/app.properties 指定apollo.property.order.enable=true

配置访问密钥

Apollo 从 1.6.0 版本开始增加访问密钥机制,从而只有经过身份验证的客户端才能访问敏感配置。如果应用开启了访问密钥,客户端需要配置密钥,否则无法获取配置。

配置方式按照优先级从高到低分别为:

1、System Property

  • 可以通过 Java 的 System Property apollo.access-key.secret (1.9.0+) 或者 apollo.accesskey.secret (1.9.0之前)来指定
  • 在Java程序启动脚本中,可以指定 java -Dapollo.access-key.secret=1cf998c4e2ad4704b45a98a509d15719 -jar xxx.jar(1.9.0+) 或者 java -Dapollo.accesskey.secret=1cf998c4e2ad4704b45a98a509d15719 -jar xxx.jar (1.9.0之前)
  • 也可以通过程序指定,如 System.setProperty("apollo.access-key.secret", "1cf998c4e2ad4704b45a98a509d15719");(1.9.0+) 或者 System.setProperty("apollo.accesskey.secret", "1cf998c4e2ad4704b45a98a509d15719"); (1.9.0之前)

2、application.properties 或者 bootstrap.properties

  • 指定 apollo.access-key.secret=1cf998c4e2ad4704b45a98a509d15719 (1.9.0+) 或者 apollo.accesskey.secret=1cf998c4e2ad4704b45a98a509d15719 (1.9.0之前)

3、System Environment

  • 还可以通过操作系统的System Environment APOLLO_ACCESS_KEY_SECRET (1.9.0+) 或者 APOLLO_ACCESSKEY_SECRET (1.9.0之前)来指定
  • 注意key为全大写

4、app.properties

  • 可以在 classpath:/META-INF/app.properties 指定apollo.access-key.secret=1cf998c4e2ad4704b45a98a509d15719 (1.9.0+) 或者 apollo.accesskey.secret=1cf998c4e2ad4704b45a98a509d15719 (1.9.0之前)

自定义 server.properties 路径

1.8.0 版本开始支持以下方式自定义 server.properties 路径,按照优先级从高到低分别为:

1、System Property

  • 可以通过 Java 的 System Property apollo.path.server.properties 来指定。
  • 在 Java 程序启动脚本中,可以指定 java -Dapollo.path.server.properties=/some-dir/some-file.properties -jar xxx.jar
  • 也可以通过程序指定,如 System.setProperty("apollo.path.server.properties", "/some-dir/some-file.properties");

2、System Environment

  • 可以通过操作系统的 System Environment APOLLO_PATH_SERVER_PROPERTIES 来指定
  • 注意 key 为全大写

开启 propertyNames 缓存

在使用 @ConfigurationProperties 注解和存在大量配置项的场景下,Spring 容器的启动速度会变慢。通过开启该配置可以显著提升启动速度,当配置发生变化时缓存会自动清理,默认为 false。

配置方式按照优先级从高到低依次为:

1、System Property

  • 可以通过 Java 的 System Property apollo.property.names.cache.enable 来指定。
  • 在 Java 程序启动脚本中,可以指定 java -Dapollo.property.names.cache.enable=true -jar xxx.jar
  • 也可以通过程序指定,如 System.setProperty("apollo.property.names.cache.enable", "true");

2、System Environment

APOLLO_PROPERTY_NAMES_CACHE_ENABLE=true

3、application.properties 或者 bootstrap.properties

apollo.property.names.cache.enable=true

4、app.properties

可以在 classpath:/META-INF/app.properties 指定如下:

apollo.property.names.cache.enable=true

ApolloLabel

ApolloLabel 是应用的标签信息,是从服务端获取配置的一个重要信息,用于灰度规则的配置。

有如下几种方式设置,按照优先级从高到低分别为:

1、System Property

Apollo 2.0.0+ 支持通过 System Property 传入 apollo.label 信息。

-Dapollo.label=YOUR-APOLLO-LABEL

2、System Environment

Apollo 2.0.0+ 支持通过操作系统的 System Environment 来传入 apollo.label 信息。

APOLLO_LABEL=YOUR-APOLLO-LABEL

3、application.properties

Apollo 2.0.0+ 支持通过 Spring Boot 的 application.properties 文件配置。

该配置方式不适用于多个 war 包部署在同一个 tomcat 的使用场景。

apollo.label=YOUR-APOLLO-LABEL

4、app.properties

在 classpath:/META-INF/app.properties 文件中。

apollo.label=YOUR-APOLLO-LABEL

覆盖系统属性

在 2.1.0 + 版本,apollo.override-system-properties 标识 Apollo 的远程属性是否应该覆盖 Java 的系统属性。默认为 true。

配置方式按照优先级从高到低分别为:

1、System Property

  • 可以通过 Java 的 System Property apollo.override-system-properties 来指定。
  • 在 Java 程序启动脚本中,可以指定 java -Dapollo.override-system-properties=true -jar xxx.jar
  • 也可以通过程序指定,如 System.setProperty("apollo.override-system-properties", "true");

2、application.properties 或者 boostrap.properties 文件中指定 apollo.override-system-properties=true

3、app.properties 文件

  • 可以在 classpath:/META-INF/app.properties 指定 apollo.override-system-properties=true

导入依赖

<dependency>
  <groupId>com.ctrip.framework.apollo</groupId>
  <artifactId>apollo-client</artifactId>
  <version>1.8.0</version>
</dependency>

客户端使用

1、API 方式

API 方式是最简单、高效使用使用 Apollo 配置的方式,不依赖 Spring 框架即可使用。

获取命名空间的配置

// 1、获取默认的命名空间的配置
Config config = ConfigService.getAppConfig();

// 2、获取properties格式的命名空间的配置
// String somePublicNamespace = "CAT";
// Config config = ConfigService.getConfig(somePublicNamespace);

// 3、获取yaml/yml格式的命名空间的配置
// Config config = ConfigService.getConfig("application.yml");

// 4、获取其它格式的命名空间的配置
// ConfigFile configFile = ConfigService.getConfigFile("test", ConfigFileFormat.XML);
// String content = configFile.getContent();

String someKey = "someKeyFromDefaultNamespace";
String someDefaultValue = "someDefaultValueForTheKey";
String value = config.getProperty(someKey, someDefaultValue);

通过 Config 的 getProperty 方法可以获取到指定属性对应的属性值。

监听配置变化事件

Config config = ConfigService.getAppConfig();
config.addChangeListener(new ConfigChangeListener() {
  @Override
  pubic void onChange(ConfigChangeEvent changeEvent) {
    System.out.println("Changes for namespace " + changeEvent.getNamespace());
    for (String key : changeEvent.changedKeys()) {
      ConfigChange change = changeEvent.getChange(key);
      System.out.println(String.format("Found change - key: %s, oldValue: %s, newValue: %s, changeType: %s", change.getPropertyName(), change.getOldValue(), change.getNewValue(), change.getChangeType()));
    }
  }
});

希望配置发生变化时得到通知。通过 Config 的 addChangeListener 方法添加一个 ConfigChangeListener 监听器。

2、Spring 整合方式

可以在代码中直接使用,如:@Value("${someKeyFromApollo:someDefaultValue}")

也可以在配置文件中使用,如:spring.datasource.url:${someKeyFromApollo:someDefaultValue}

甚至可以直接托管 Spring 中的配置。如:在 Apollo 中直接配置 spring.datasource.url=jdbc:mysql://localhost:3306/somedb

支持 Spring Boot 的 @ConfigurationProperties 方式。

也支持结合 API 方式使用,如:@ApolloConfig private Config config;

2.1 配置

2.1.1 基于 Spring 的配置

注入默认的命名空间的配置到 Spring 中

@Configuration
@EnableApolloConfig
public class AppConfig {
  
}

注入多个命名空间的配置到 Spring 中

@Configuration
@EnableApolloConfig({"FX.apollo", "application.yml"})
public class AnotherAppConfig {
  
}

注入多个命名空间的配置到 Spring 中,并且指定顺序

在 @EnableApolloConfig 注解中的 order 属性指定顺序,值越小则顺序越靠前。

@Configuration
@EnableApolloConfig(order = 2)
public class AppConfig {
  
}

@Configuration
@EnableApolloConfig(value = {"FX.apollo", "application.yml"}, order = 1)
public class AnotherAppConfig {
  
}

2.1.2 基于 Spring Boot 的配置

额外支持通过 application.properties / bootstrap.properties 进行配置,该方式可以使配置在更早的阶段注入,比如使用 @ConditionalOnProperty 的场景或者有一些 spring-boot-starter 在启动阶段就需要读取配置然后做一些事情。

# 启动阶段注入application命名空间的配置
apollo.bootstrap.enabled = true

也支持注入多个命名空间的配置。

# 启动阶段注入application,FX.apollo,application.yml命名空间的配置
apollo.bootstrap.enabled = true
apollo.bootstrap.namespaces = application,FX.apollo,application.yml

可以让 Apollo 的加载顺序在日志系统之前,比如希望把日志相关的配置(logging.level.root=info 或者 logback-spring.xml 中的参数)也交给 Apollo 管理。

# 启动阶段注入application命名空间的配置
apollo.bootstrap.enabled = true
# 让 Apollo 的加载顺序在日志系统之前
apollo.bootstrap.eagerLoad.enabled = true

2.1.3 基于 Spring Boot Config Data Loader 的配置

详细内容参考官方文档 - Spring Boot Config Data Loader

2.2 使用

2.2.1 Spring Placeholder 的使用

在 Spring 环境中,可以使用占位符的形式注入配置,如:${someKey:someDefaultValue}

建议在实际使用时尽量给出默认值,以免由于 key 没有定义导致运行时错误。

从 v0.10.0 版本开始,支持占位符的运行时自动更新。想要关闭占位符的运行时自动更新,可以选择如下任意方法:

1、通过设置系统参数,如启动时传入 -Dapollo.autoUpdateInjectedSpringProperties=false

2、通过设置 META-INF/app.properties 中的 apollo.autoUpdateInjectedSpringProperties 属性,如:

app.id = SampleApp
apollo.autoUpdateInjectedSpringProperties = false
2.2.1.1 XML 中占位符的使用

假设 TestXmlBean 中有两个配置项需要注入。

public class TestXmlBean {
  private int timeout;
  private int batch;
 
  public void setTimeout(int timeout) {
    this.timeout = timeout;
  }

  public void setBatch(int batch) {
    this.batch = batch;
  }
 
  public int getTimeout() {
    return timeout;
  }
 
  public int getBatch() {
    return batch;
  }
}

在 xml 中使用如下方式进行定义。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:apollo="http://www.ctrip.com/schema/apollo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd">
    <apollo:config/>
    <bean class="com.ctrip.framework.apollo.spring.TestXmlBean">
        <property name="timeout" value="${timeout:100}"/>
        <property name="batch" value="${batch:200}"/>
    </bean>
</beans>
2.2.1.2 Java Config 中占位符的使用

假设 TestJavaConfigBean 中,需要注入两个属性。

public class TestJavaConfigBean {
  @Value("${timeout:100}")
  private int timeout;
  private int batch;
 
  @Value("${batch:200}")
  public void setBatch(int batch) {
    this.batch = batch;
  }
 
  public int getTimeout() {
    return timeout;
  }
 
  public int getBatch() {
    return batch;
  }
}
@Configuration
@EnableApolloConfig
public class AppConfig {
  
  @Bean
  public TestJavaConfigBean javaConfigBean() {
    return new TestJavaConfigBean();
  }
}

2.2.2 ConfigurationProperties 的使用

Spring Boot 提供了 @ConfigurationProperties 注解用于将配置注入到 bean 对象中。

Apollo 也支持这种方式。

@ConfigurationProperties(prefix = "redis.cache")
public class SampleRedisConfig {
  private int expireSeconds;
  private int commandTimeout;

  public void setExpireSeconds(int expireSeconds) {
    this.expireSeconds = expireSeconds;
  }

  public void setCommandTimeout(int commandTimeout) {
    this.commandTimeout = commandTimeout;
  }
}
@Configuration
@EnableApolloConfig
public class AppConfig {
  @Bean
  public SampleRedisConfig sampleRedisConfig() {
    return new SampleRedisConfig();
  }
}

需要注意的是,@ConfigurationProperties 如果需要在配置发生变化时自动更新注入的值,需要配合使用 EnvironmentChangeEvent 或者 RefreshScope,可以参考 EnvironmentChangeEvent 样例RefreshScope 样例1RefreshScope 样例2

2.2.3 Spring Annotation 的使用

Apollo 在 Spring 环境中,提供了如下三个注解:

  • @ApolloConfig:用来自动注入 Config 对象。
  • @ApolloConfigChangeListener:用来自动注册 ConfigChangeListener。
  • @ApolloJsonValue:用来将配置的 json 字符串自动注入为对象。
public class TestApolloAnnotationBean {
  
  @ApolloConfig
  private Config config;					 // 注入“application”命名空间的配置
  
  @ApolloConfig("application")
  private Config anotherConfig;		 // 注入“application”命名空间的配置
  
  @ApolloConfig("FX.apollo")
  private Config yetAnotherConfig; // 注入“FX.apollo”命名空间的配置
  
  @ApolloConfig("application.yml")
  private Config ymlConfig;				 // 注入“application.yml”命名空间的配置
  
  /**
   * jsonBeanProperty=[{"someString":"hello","someInt":100},{"someString":"world!","someInt":200}]
   */
  @ApolloJsonValue("${jsonBeanProperty:[]}")
  private List<JsonBean> anotherJsonBeans;	// 将“jsonBeanProperty”字符串解析并注入
  
  @Value("${batch:100}")
  private int batch;
  
  @ApolloConfigChangeListener
  public void someOnChange(ConfigChangeEvent changeEvent) {	// 监听“application”命名空间的配置的变化
    if (changeEvent.isChanged("batch")) {
      this.batch = config.getIntProperty("batch", 100);
    }
  }
  
  @ApolloConfigChangeListener({"application", "FX.apollo", "application.yml"})
  public void yetAnotherOnChange(ConfigChangeEvent changeEvent) {	// 监听“application”、“FX.apollo”、“application.yml”命名空间的配置的变化
    
  }
  
}
@Configuration
@EnableApolloConfig
public class AppConfig {
  
  @Bean
  public TestApolloAnnotationBean testApolloAnnotationBean() {
    return new TestApolloAnnotationBean();
  }
}

2.2.4 已有配置迁移

详细内容参考官方文档 - 已有配置迁移

 类似资料: