概述
假设现在有个需求:
我们的应用部署在 10 台机器上, 当我们调整完某个配置参数时, 无需重启机器, 10 台机器自动能获取到最新的配置.
如何来实现呢? 有很多种, 比如:
1,
将配置放置到一个数据库里面
, 应用每次读取配置都是直接从 DB 读取. 这样的话, 我们只需要做一个 DB 变更, 把最新的配置信息更新到数据库即可. 这样无论多少台应用, 由于都从同一个 DB 获取配置信息, 自然都能拿到最新的配置.
2,
每台机器提供一个更新配置信息的 updateConfig 接口
, 当需要修改配置时, 挨个调用服务器的 updateConfig 接口.
3, 借助 redis 来实现, 把配置信息放置到 redis 上, 但是这样子, 就每次都得去 redis 读取, 多了一些网络请求.
上面这三种方法是最容易想到的, 也很容易做, 但是缺点当然也非常的多. 虽说缺点很多, 但是某些传统企业还真是这么干的.
在互联网企业里, 基本没见过这么玩的, 都是会使用分布式配置中心. 用开源的或者自己实现, 目前开源的分布式配置中心有很多, 而
spring cloud config
就是其中的佼佼者. 下面我们就用
spring cloud config
来实现一个分布式配置中心.
是否使用最新的 Spring Boot 2.0 版本
我曾经使用最新的 spring cloud 2.0 做了一个分布式是配置中心的 demo. 原本以为很简单, 但是居然足足花了一天才搞定. 有以下几个原因:
1,spring cloud 对应的文档没有完全更新, 出了问题, 在文档里找不着;
2, 目前使用 2.0 版本的公司很少, 网上也没什么具体实战文章介绍. 出了问题后, 百度是找不到解决方案的. 而 google 也基本很难找到方案, 都是一些零星的知识碎片;
3,2.0 这个版本, config 和 bus 这块有些小变动, 如果还按照 1.5.x 的版本来弄的话, 是行不通的.
基于上面几个原因, 建议使用 1.5.x 的版本靠谱些. 下面这篇文章会以下面的版本来介绍的:
- spring boot:
- 1.5.2.RELEASE
对应的 spring cloud 使用:
Dalston.RELEASE
搭建 spring cloud config server
如果你只是想把配置统一由 spring cloud config 来管理, 而暂时不想做配置中心的高可用的话, 则只需要 config 和 bus 两个组件就够了. 但是如果要保证高可用, 还得使用 spring cloud 的注册发现组件.
除了 config 和 bus 之外, 我们还需要使用 git. 因为 spring cloud config 是使用 git 来做版本管理的.
基于 spring cloud config 做一个配置中心, 很简单, 只要几个小步骤就搞定了.
[1] 引入 config 和 bus 组件
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-config-server</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-bus-amqp</artifactId>
- </dependency>
[2] 启动类使用 @EnableConfigServer 注解
- package spring.cloud.config;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.cloud.config.server.EnableConfigServer;
- @EnableConfigServer
- @SpringBootApplication
- public class ConfigApplication {
- public static void main(String[] args) {
- SpringApplication.run(ConfigApplication.class, args);
- }
- }
[3] application.yml 文件配置 rabbitmq 和 git 仓库
- server:
- port: 8040
- spring:
- application:
- name: spring-cloud-config-server
- cloud:
- config:
- server:
- git:
- uri: https://gitlab.xxxxxx.com/config/xxxxxxx.git
- search-paths:
- username: xxxxx
- password: xxxxxx
- activemq:
- host: 127.0.0.1
- port: 5672
- username: guest
- password: guest
- management:
- security:
- enabled: false
配置 RabbitMQ 是因为 bus 组件需要使用它来通知客户端, 配置有变动. 另外, 记得使用
- management:
- security:
- enabled: false
将验证关闭掉, 不然后面的操作, 老是报授权错误.
到此服务端配置中心已经搞定了. 现在你就可以在服务端先做个小实验, 提交一个
demo-dev.properties
文件, 文件的内容如下:
address=hello
然后使用
http://localhost:8040/demo/dev
如果能输出
{"address":"hello"}
就说明 spring cloud config 跟 git 的交互是 ok 的.
客户端接入配置中心
我们的目标:
当把配置信息修改完提交到 git 上后, 所有接入到 spring cloud config 的客户端马上能收到通知, 并且拿到最新的配置信息.
下面介绍如何实现这个目标.
客户端只需要做几个小步骤即可完成接入动作.
[1] 引入依赖
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-config</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-bus-amqp</artifactId>
- </dependency>
引入
spring-boot-starter-web
只是为了做实验而已.
[2] 配置 RabbitMQ 和引入配置中心的 url
- application.properties
- spring.application.name=spring-cloud-config-client1
- server.port=8042
- management.security.enabled=false
- spring.rabbitmq.host=127.0.0.1
- spring.rabbitmq.port=5672
- spring.rabbitmq.username=guest
- spring.rabbitmq.password=guest
- bootstrap.properties
- spring.cloud.config.name=demo
- spring.cloud.config.profile=dev
- spring.cloud.config.label=master
- spring.cloud.config.uri=http://localhost:8040/
有三个注意点:
1, 关闭验证: management.security.enabled=false
2,spring cloud config 相关的配置一定一定要放到 bootstrap.properties 里
3, 使用 spring.cloud.config.uri 指定配置中心的地址
另外, 对于客户端来说,
启动类是不用加上任何跟 config 和 bus 有关的注解的
.
到此客户端搞定了, 我们可以使用一个 controller 来开始做实验了.
- package springcloudconfig.client;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.cloud.context.config.annotation.RefreshScope;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- @RestController
- @RefreshScope
- public class HelloController {
- @Value("${address}")
- private String address;
- @RequestMapping("/address")
- public String getAddress() {
- return this.address;
- }
- }
假设上面的 HelloController 需要用到 address 这个配置, 只需要使用 @RefreshScope 和 @value 注解就可以了
- @RefreshScope
- public class HelloController {}
- @Value("${address}")
- private String address;
为了验证客户端是否能拿到最新的配置信息, 提供一个
- @RequestMapping("/address")
- public String getAddress() {
- return this.address;
- }
方法.
我们修改一下
demo-dev.properties
文件, 将值改成
address=hello update
并提交到 git 上. 这个时候我们调用 getAddress 接口
http://localhost:8041/address
发现并没有拿到最新的值. 那是因为 push 到 git 的这个动作做完后, 我们没有通知到 spring cloud bus. 可以使用 postman 来做一个 post 请求, 调用如下接口, 来通知 bus.
http://localhost:8040/bus/refresh
这个接口一旦调用成功, bus 会利用 RabbitMQ 通知所有的客户端, 配置已经更新.
特别注意:
我们是调用服务端的 / bus/refresh 接口, 不是去调用客户端的 / bus/refresh 接口.
如果每次提交, 都要去调用服务端的 / bus/refresh 接口, 那这个也太麻烦了. 可以使用 webhook 来帮一下忙.
如果你们用的是新的 gitlab, 那么只需要在工程里面, 点击 [Settings] , 再点击 [Integrations] , 就可以设置 webhook 了, 如下图:
url 里面填入配置中心服务端的 / bus/refresh 接口地址, 然后点击 [添加 Webhook] 就可以了.
与携程的阿波罗对比
请参看: apollo 相比于 spring-cloud-config 有什么优势 https://github.com/ctripcorp/apollo/wiki/FAQ#9-apollo相比于spring-cloud-config有什么优势
我个人还是推荐使用 Spring Cloud Config, 很轻量级, 且社区活跃, 遇到问题很好找到解决方案. 另外呢, 我个人认为阿波罗和 Spring Cloud Config 的区别就只是有木有界面而已. 界面做得到的, 我们通过 git 也可以的, 只是用户体验没那么好而已.
来源: https://juejin.im/entry/5aed4856f265da0ba60fae4e