Spring Cloud 配置中心

目录
  1. 1. 闲话配置
  2. 2. Spring Boot 的配置管理
    1. 2.1. 这还不够
  3. 3. Spring Cloud Config
    1. 3.1. 实操进阶
      1. 3.1.1. 热更新
      2. 3.1.2. 添加权限
      3. 3.1.3. 加载多组配置文件
  4. 4. 一些问题
    1. 4.1. @EventListener 与 SpEL
    2. 4.2. 权限管理
    3. 4.3. JSON 文件的读取和解析
  5. 5. 相关选择
  6. 6. 参考文献

闲话配置

老司机都喜欢在程序设计中尽可能的把各种参数做成可配置的,等到产品需求发生改动的时候,优雅的修改一行配置,重新加载一次配置,就满足了需求。

配置(Configuration)是不修改代码的情况下,对程序的运行调整的能力。

简单来讲,配置可以分成两类:

  1. 系统配置:包括线程池大小、数据库连接等,变化频率较低
  2. 业务配置:功能开关,功能参数等,变化较为频繁

程序的配置一般而言,分为几个环境:

  1. 开发环境
  2. 测试环境
  3. 生产环境

这几个环境的配置是有差异的,所以配置管理功能应当能够根据当前环境读取对应的配置。

前面提到的不修改代码,只是最低要求,相当多的情况下,程序是不能停机的,这就提出了热更新的需求。

另外,配置的修改应该是有记录可追溯的。

Spring Boot 的配置管理

Spring 实现了非常友好的配置读取方式,

Spring Boot 程序默认使用 application.properties 进行配置。

例如一个参数:

1
flag=0

在程序中可以通过:

1
2
@Value("${flag})
int flag;

来读取。

也可以通过设置多个配置文件:

1
2
3
4
application.properties
application-dev.properties
application-test.properties
application-prod.properties

application-dev.properties

1
flag=1

application-test.properties

1
flag=2

application-prod.properties

1
flag=3

和在 application.properties 中声明当前的活跃的 profile:

1
spring.profiles.active=dev

来实现根据运行环境切换配置信息。

以上只是 Spring 强大的配置能力的冰山一角,有兴趣可以参考外部配置文档

这还不够

其实以上描述的 Spring Boot 的配置能力已经很强了,但是有个很致命的问题——无法热更新。

如果非得实现热更新,那可以把配置做成 JSON 文件,再实现一个 endpoint,重新读取一次配置。

假设有一千个实例呢?

Spring Cloud Config

项目 github:https://github.com/spring-cloud/spring-cloud-config

简介:External configuration (server and client) for Spring Cloud

这个项目包含两部分:

  • Server

负责从 git/svn 等版本管理系统中读取配置,并以 http 的方式提供服务。

  • Client

根据客户端配置,从指定的 Server 中读取对应配置,并且与 Spring 本身的 PropertyResource 和 Environment 无缝结合。同时,提供了统一的方式进行配置热更新。

对于这个系统的基础配置和运行,可以参阅下面两个 url:

https://spring.io/guides/gs/centralized-configuration/

http://blog.didispace.com/spring-cloud-starter-dalston-3/

实操进阶

热更新

Spring Cloud Config 实现了非常优雅的热更新。

  • 客户端的配置 Bean 添加 @RefreshScope
1
2
3
4
5
6
7
8
9
10
@Configuration
@RefreshScope
public class ConsumeConfig {

@Value("${consume.desc}")
private String consumeDesc;

@Value("#{'${api.server.round.card}'.split(',')}")
private List<String> cardList;
}

在配置这个注解之后,调用客户端的 /refresh endpoint,这个 Bean 就会刷新,同时个 Bean 的依赖方下次方法调用时也会更新 Bean 引用。

有些时候,你需要监听这个更新事件,把拿到的最新配置,重新初始化一些部件。那你可以添加:
@EventListener(EnvironmentChangeEvent.class) 这个 annotation。

1
2
3
4
5
6
7
8
9
10
11
@Component
public class ConsumeService {

@Autowired
ConsumeConfig consumeConfig;

@EventListener(EnvironmentChangeEvent.class)
void onEnvChange() {
//do re-init stuff
}
}

添加权限

Config Server 任何人都可以通过 http 访问配置,这个不大好,建议加上认证,最简单是使用 Spring-Security 添加一个 basic authentication。

  • 服务器端配置

build.gradle 添加依赖:

1
2
3
dependencies {
compile('org.springframework.boot:spring-boot-starter-security')
}

application.properties 添加密码(用户名默认是 user):

1
security.user.password=xxx

重启服务器,再次通过 http 访问配置的时候需要验证。

  • 客户端配置

服务器端做了验证,那客户端也需要添加相应的配置:

bootstrap.yml

1
2
3
4
5
6
7
8
9
spring:
application:
name: application
cloud:
config:
uri: http://yourhost.com
profile: dev
username: user
password: xxx

加载多组配置文件

很多时候,为了避免 application.properties 过于臃肿,你可能需要把一些配置文件拆出来,例如专门负责邀请奖励的配置:

1
2
3
4
invite.properties
invite-dev.properties
invite-test.properties
invite-prod.properties

同样,也区分了多个环境。

那在使用 Spring Cloud 的时候如何读取这个文件呢?

1
2
3
spring:
application:
name: application,invite

注意上面的 application.name 是以逗号分隔的两组配置名称。

一些问题

@EventListener 与 SpEL

我在实际使用中发现,在事件监听函数中,使用更新后的配置的时候:

1
2
3
4
5
@Value("${consume.desc}")
private String consumeDesc;

@Value("#{'${api.server.round.card}'.split(',')}")
private List<String> cardList;

第一个配置是使用 @Value 绑定一个字符串类型,第二个配置是使用 @Value 中的 SpEL 去将配置中的字符串,切割成 List。

我发现第二个,无法切割成功。试验了多次,还没有找到答案。我已经在 Spring Cloud Config 的 github 上提交了 issue

如果有了解这个的,请不吝赐教。

update 2017-10-26

权限管理

在不做二次开发的情况下,这个配置中心的数据是对所有的 client 开放的。某些情况下,这种设定并不合适。

JSON 文件的读取和解析

Spring Cloud Config 本身是可以通过 http 来提供 JSON 文件的访问的,但是Spring Boot 原生并不支持 JSON 配置的读取和解析。

相关选择

其实配置管理工具,选择还是不少的,下面列举一下。

配置文件管理,可以热更新,跟 Spring 没有绑定。

专注管理配置文件,也可以实现热更,跟 Spring 没有绑定。

携程开源的,功能很全

百度的一位工程师的开源项目,功能也很全

来自阿里的开源,有些日子了

参考文献

http://blog.didispace.com/spring-cloud-starter-dalston-3/

http://cloud.spring.io/spring-cloud-config/single/spring-cloud-config.html

http://jm.taobao.org/2016/09/28/an-article-about-config-center/

https://blog.coding.net/blog/spring-cloud-config

本文由 kvh 创作,采用 CC BY 3.0 CN协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。
相关文章推荐

No related post.