一个微服务系统是由多个微服务组成,这些微服务通常会有很多相同的配置(即application.yml),由于服务众多,如果对于一项公共配置发生变更,比如数据库的地址。那么就需要将所有设计到的服务全部更新,并且重启以重新读取配置文件。这如果对于几百个服务构成的系统来说,就要了人命了。所以针对微服务要实现集中管理微服务配置、不同环境不同配置、运行期间也可动态调整、配置修改后可以自动更新的需求,分布式配置中心spring cloud config应运而生。
Spring Cloud Config 分为Config Server和Config Client两部分,是一个可以横向扩展,集中式的配置服务器, 默认使用Git存储配置内容,它也支持配置文件放在在配置服务的内存中,也支持放在远程svn仓库里。
引入spring cloud config后,我们的外部配置文件就可以集中放置在一个git仓库里,再新建一个config server,用来管理所有的配置文件,维护的时候需要更改配置时,只需要更改远程仓库的配置文件,所有的服务实例都可以通过config server来获取配置文件,这时每个服务实例就相当于配置服务的客户端config client。
为了保证系统的稳定,配置服务端config server可以进行集群部署,即使某一个实例,因为某种原因不能提供服务,也还有其他的实例保证服务的继续进行。
1. Config Server
创建一个maven工程eureka-config-server,pom里引用依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent</artifactId>
<groupId>com.cjc.spring.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.cjc.spring.cloud</groupId>
<artifactId>eureka-config-server</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
启动类里添加注解@EnableConfigServer,@EnableEurekaClient
package com.cjc.spring.cloud.config.server.main;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ApplicationMain {
public static void main(String arg[]){
SpringApplication.run(ApplicationMain.class);
}
}
application.yml中配置spring.cloud.config.server,同时将该服务注册到eureka server里面,改变ip端口多启动几个就形成config server集群,而eureka client 访问eureka server的时候要用 serviceId: eureka-config-server 配置中心的servieId即服务名来访问,而不是通过 uri: http://localhost:8086/指明配置服务中心的网址。这样就能通过eureka来实现配置中心的负载均衡和高可用。
server:
port: 8086
spring:
application:
name: eureka-config-server
cloud:
config:
server:
git:
uri: https://github.com/cxsummer/SpringCloudConfig.git #自己git地址
searchPaths: respo #文件目录
username: #账号
password: #密码
label: master #分支
management:
endpoints:
web:
exposure:
include: "*" #暴露所有端点
eureka:
client:
register-with-eureka: true #false表示不向注册中心注册自己。
fetch-registry: true #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
serviceUrl:
defaultZone: http://localhost:8081/eureka/
启动后访问http://localhost:8086/base-config/dev
{"name":"base-config","profiles":["dev"],"label":null,"version":"6e2ff0b1bd892292d655c9b747e8e5615b67bcbf","state":null,"propertySources":[{"name":"https://github.com/cxsummer/SpringCloudConfig.git/respo/base-config-dev.yml","source":{"spring.zipkin.base-url":"http://localhost:9411","base-name":"summer2"}}]}
这个source就是我们在git里面的base-config-dev.yml的值
证明配置服务中心可以从远程程序获取配置信息,http请求地址和资源文件映射如下:,可参考
· /{application}/{profile}[/{label}]
· /{application}-{profile}.yml
· /{label}/{application}-{profile}.yml
· /{application}-{profile}.properties
· /{label}/{application}-{profile}.properties
2. Config Client
改造user-action工程添加config client
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
新建bootstrap.yml并添加以下内容,这个文件是启动时优先加载。
spring:
application:
name: eureka-user
cloud:
config:
name: eureka-user,base-config # 和git里的文件名对应
label: master # 远程仓库的分支
profile: dev # dev 开发环境配置文件 | test 测试环境 | pro 正式环境
#uri: http://localhost:8086/ # 指明配置服务中心的网址
discovery:
enabled: true #从配置中心读取文件
serviceId: eureka-config-server #配置中心的servieId,即服务名
eureka:
client:
register-with-eureka: true #false表示不向注册中心注册自己。
fetch-registry: true #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
serviceUrl:
defaultZone: http://localhost:8081/eureka/
由此可见我们引用git中的两个文件eureka-user,base-config。我们试着读取base-config的base-name属性。
在Controller里面添加以下代码
@Value("${base-name}")
private String foo;
@RequestMapping("/getConfig")
public String getConfig(){
return foo;
}
启动user-action,并访问http://localhost:8082/getConfig
可以看到页面显示 summer2
由此我们可以从git上读取配置文件了
3. 配置刷新
有一个问题是如果修改了git配置文件,那么按传统模式的架构,引用此配置文件的微服务要想获取修改后的值就必须重启服务。而在spring cloud config中,添加spring-boot-starter-actuator监控依赖,其中包含/refresh
端点的实现,该端点将用于实现客户端应用配置信息的重新获取与刷新。user-action添加以下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
在客户端上需要注入配置值的类上加入注解@RefreshScope
application.yml中暴漏刷新端点
management:
endpoints:
web:
exposure:
include: refresh
启动user-action,并访问http://localhost:8082/getConfig
可以看到页面显示 summer2
使用post方法(一定要post)请求http://localhost:8082/actuator/refresh
可以看到页面显示 summer3