== Spring Cloud Alibaba Cloud ACM

Spring Cloud AliCloud ACM 是阿里云提供的商业版应用配置管理(Application Configuration Management) 产品 在 Spring Cloud 应用侧的客户端实现，且目前完全免费。

Spring Cloud AliCloud ACM 是 Config Server 和 Client 的替代方案，客户端和服务器上的概念与 Spring Environment 和 PropertySource 有着一致的抽象，在特殊的 bootstrap 阶段，配置被加载到 Spring 环境中。当应用程序通过部署管道从开发到测试再到生产时，您可以管理这些环境之间的配置，并确保应用程序具有迁移时需要运行的所有内容。

=== 如何引入 Spring Cloud AliCloud ACM

Spring Cloud Alibaba 已经发布了 0.2.2.BUILD-SNAPSHOT 版本，需要首先导入依赖管理POM。

[source,xml]
----
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>0.2.2.BUILD-SNAPSHOT</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
----

接下来引入 Spring Cloud AliCloud ACM Starter 即可。

[source,xml]
----
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-alicloud-acm</artifactId>
</dependency>
----

=== 使用 ACM 进行配置管理

当客户端引入了 Spring Cloud AliCloud ACM Starter 以后，应用启动时会自动从配置管理的服务端获取配置信息，并注入到 Spring 的 Environment 中。

以下是一个简单的应用示例。

[source,java]
----
@SpringBootApplication
public class ProviderApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(ProviderApplication.class, args);
        String userName = applicationContext.getEnvironment().getProperty("user.name");
        String userAge = applicationContext.getEnvironment().getProperty("user.age");
        System.err.println("user name :"+userName+"; age: "+userAge);
    }
}
----

既然需要从配置中心服务端获取配置信息，那么肯定需要配置服务端的地址，在 bootstrap.properties 中，还需要配置上以下信息。

[source,properties]
----
# 必选，应用名会被作为从服务端获取配置 key 的关键词组成部分
spring.application.name=acm-config
server.port=18081
# 以下就是配置中心服务端的IP和端口配置
spring.cloud.alicloud.acm.server-list=127.0.0.1
spring.cloud.alicloud.acm.server-port=8080
----

NOTE: 此时没有启动配置中心，启动应用会报错，因此在应用启动之前，应当首先启动配置中心。


=== 启动配置中心

ACM 使用的配置中心有两种，一种是完全免费的轻量版配置中心，主要用于开发和本地调试，一种是云上配置中心ACM。通常情况下，可以使用轻量版配置中心作为开发和测试环境，使用云上的 ACM 作为灰度和生产环境。

==== 启动轻量版配置中心

轻量版配置中心的下载和启动方式可参考 https://help.aliyun.com/document_detail/44163.html?spm=a2c4g.11186623.6.677.5f206b82Z2mTCF[这里]

NOTE: 只需要进行第1步（下载轻量配置中心）和第2步（启动轻量配置中心）即可，第3步（配置hosts）在与 ACM 结合使用时，不需要操作。


==== 使用云上配置中心

使用云上 ACM ，可以省去服务端的维护工作，同时稳定性也会更有保障。当使用云上配置中心时，代码部分和使用轻量配置中心并没有区别，但是配置上会有一些区别。

以下是一个简单的使用云上配置中心的配置示例，配置详情需要在 https://acm.console.aliyun.com[ACM控制台查询]

[source,properties]
----
# 应用名会被作为从服务端获取配置 key 的关键词组成部分，因此是必选
spring.application.name=ans-provider
# 端口配置自由配置即可
server.port=18081
# 以下就是配置中心的IP和端口配置
spring.cloud.alicloud.acm.server-mode=EDAS
spring.cloud.alicloud.access-key=你的阿里云AK
spring.cloud.alicloud.secret-key=你的阿里云SK
spring.cloud.alicloud.acm.endpoint=acm.aliyun.com
spring.cloud.alicloud.acm.namespace=你的 ACM namespace，需要在 ACM 控制台查询
----

NOTE: EDAS 提供应用托管服务，如果你将应用托管到 EDAS，那么 EDAS 将会自动为你填充所有配置。

=== 在配置中心添加配置

1. 启动好轻量版配置中心之后，在控制台中添加如下的配置。

[source,subs="normal"]
----
Group:      DEFAULT_GROOUP

DataId:     acm-config.properties

Content:    user.name=james
            user.age=18
----

NOTE: DataId 的格式为 `{prefix}. {file-extension}`,prefix 默认从配置 spring.application.name 中取值，file-extension 默认的值为 "properties"。

=== 启动应用验证

启动这个Example，可以在控制台看到打印出的值正是我们在轻量版配置中心上预先配置的值。

[source,subs="normal"]
----
user name :james; age: 18
----

=== 更改配置文件扩展名

spring-cloud-starter-alicloud-acm 中 DataId 默认的文件扩展名是 properties。除去 properties 格式之外，也支持 yaml 格式。
支持通过 spring.cloud.alicloud.acm.file-extension 来配置文件的扩展名，yaml 格式可以配置成 `yaml` 或 `yml`。

NOTE: 修改文件扩展名后，在配置中心中的 DataID 以及 Content 的格式都必须做相应的修改。

=== 支持配置的动态更新

spring-cloud-starter-alicloud-acm 默认支持配置的动态更新，当您在配置中心修改配置的内容时，会触发 Spring 中的 Context Refresh 动作。
带有 @RefreshScope 和 @ConfigurationProperties 注解的类会自动刷新。

NOTE: 你可以通过配置 spring.cloud.alicloud.acm.refresh.enabled=false 来关闭动态刷新

=== profile 粒度的配置

spring-cloud-starter-alicloud-acm 在加载配置的时候，首先会尝试去加载 dataid 为{spring.application.name}.{file-extension}的配置，当设置了 spring.profiles.active 中配置有内容时，还会尝试依次去加载 spring.profile 对应的内容， dataid 的格式为{spring.application.name}-{profile}.{file-extension}的配置，且后者的优先级高于前者。

spring.profiles.active 属于配置的元数据，所以也必须配置在 bootstrap.properties 或 bootstrap.yaml 中。比如可以在 bootstrap.properties 中增加如下内容。

[sources,properties]
----
spring.profiles.active={profile-name}
----

Note: 也可以通过 JVM 参数 -Dspring.profiles.active=develop 或者 --spring.profiles.active=develop 这类优先级更高的方式来配置，只需遵循 Spring Boot 规范即可。



=== 支持自定义 Group 的配置

在没有明确指定 `{spring.cloud.alicloud.acm.group}` 配置的情况下， 默认使用的是 DEFAULT_GROUP 。如果需要自定义自己的 Group，可以通过以下配置来实现：

[source,properties]
----
spring.cloud.alicloud.acm.group=DEVELOP_GROUP
----

NOTE: 该配置必须放在 bootstrap.properties 文件中。并且在添加配置时 Group 的值一定要和 `spring.cloud.alicloud.acm.group` 的配置值一致。

==== 支持共享配置

ACM 提供了一种多个应用之间共享配置中心的同一个配置的推荐方式，供多个应用共享一些配置时使用，您在使用的时候需要添加在 bootstrap 中添加一个配置项 `spring.application.group`。

[source,properties]
----
spring.application.group=company.department.team
----

这时你的应用在获取之前提到的自身所独有的配置之前，会先依次从这些 DataId 去获取，分别是 company:application.properties, company.department:application.properties, company.department.team:application.properties。
然后，还会从 {spring.application.group}:{spring.application.name}.{file-extension} 中获取
越往后优先级越高，最高的仍然是应用自身所独有的配置。


NOTE: 共享配置中 DataId 默认后缀为 properties，可以通过 spring.cloud.alicloud.acm.file-extension 配置. `{spring.application.group}:{spring.application.name}.{file-extension}` 。

NOTE: 如果设置了 `spring.profiles.active` ，DataId 的格式还支持 `{spring.application.group}:{spring.application.name}-{spring.profiles.active}.{file-extension}`。优先级高于 `{spring.application.group}:{spring.application.name}.{file-extension}`
