一、前言
上一篇文章已经实现了Spring Cloud Config分布式配置中心的功能,我们已经可以通过Config Server获取Git远程仓库配置文件中的内容,但是在实际项目中,当服务实例数量比较多的情况下,每个服务单元都从配置中心获取配置信息,假如配置中心由于网络等原因挂掉了,这时候会导致那些服务实例请求失败等一系列问题。这时候可以考虑将配置中心做成一个微服务,注册到Eureka中,这样启动多个Config Server就可以实现负载均衡,从而实现配置中心的高可用。
二、准备工程
a. springcloud_eureka_server: 服务注册中心,端口1111
b. springcloud_hign_availability_config_server: 高可用配置中心,端口2222
c. springcloud_config_client: 具体服务单元,端口3333
本文对怎么搭建Eureka服务注册中心不做过多讲解,可以参考前面文章。
三、新建springcloud_hign_availability_config_server工程
因为要将配置中心作为一个服务注册到eureka中,所以注意引入config-server以及eureka的依赖,具体pom.xml:
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.springcloud.wsh</groupId>
<artifactId>springcloud__hign_availability_config_server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springcloud__hign_availability_config_server</name>
<description>高可用Config配置中心</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Camden.SR6</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
四、启动类加上@EnableConfigServer以及@EnableDiscoverClient注解
/**
* @Description: 实际项目中当服务单元很多时,每个服务单元都从配置中心读取文件,这时可以将配置中心做成一个微服务(注册到eureka),将其集群化(负载均衡),达到高可用
* @Author: WeiShiHuai
* @Date: 2018/9/19 9:53
*/
@SpringBootApplication
//@EnableDiscoveryClient作用: 让config-server配置中心成为eureka的服务端,通过负载均衡实现高可用
@EnableDiscoveryClient
//开启分布式配置功能
@EnableConfigServer
public class SpringcloudHignAvailabilityConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudHignAvailabilityConfigServerApplication.class, args);
}
}
@EnableDiscoveryClient : 让config-server配置中心成为eureka的服务端,通过负载均衡实现高可用
@EnableConfigServer: 开启分布式配置功能
五、config-server的配置文件application.yml
配置文件需要配置git仓库地址,访问路径,分支,访问用户名,密码等,注意需要配置
#配置注册到eureka服务注册中心的地址
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/eureka/
以上配置将配置中心注册到Eureka上,别的服务就可以通过serviceId指定配置中心的地址,从而实现配置中心高可用。具体配置文件如下图:
#配置注册到eureka服务注册中心的地址
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/eureka/
#端口号
server:
port: 2222
# port: 4444
#应用名称
spring:
application:
name: hign-availability-config-server
cloud:
config:
server:
git:
#git远程仓库地址
uri: 对应你的git仓库地址
#访问git仓库的用户名(公开仓库不需要配置用户名和密码,私有仓库才需要配置)
username: 对应你的git用户名
#访问git仓库的密码
password: 对应你的git密码
#git仓库配置文件的路径
search-paths: repository
#git仓库分支(默认master)
label: master
注意:这里还需要将上篇文章解决中文乱码的问题加到config-server中,防止出现中文乱码问题,具体可以参考上篇文章。
六、新建config-client工程
注意加入spring-cloud-starter-config、 spring-cloud-starter-eureka依赖,具体pom.xml:
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.springcloud.wsh</groupId>
<artifactId>springcloud_config_client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springcloud_config_client</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Camden.SR6</spring-cloud.version>
</properties>
<dependencies>
<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-eureka</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
这时候,启动类需要加上@EnableDiscoverClient注册为Eureka的服务客户端。
@SpringBootApplication
@EnableDiscoveryClient
public class SpringcloudConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudConfigClientApplication.class, args);
}
}
七、config-client配置文件bootstrap.yml
注意名称是bootstrap.yml。
server:
port: 3333
#注意application-name(配置文件前缀)需要对应git仓库中 config-client-dev、config-client-test、config-client-prod为名称的配置文件
spring:
application:
name: config-client
cloud:
config:
#指定当前所属环境
profile: prod
discovery:
#开启通过服务访问config-server的功能
enabled: true
#指定配置中心注册到eureka的serviceId(即config-server的application-name)
serviceId: hign-availability-config-server
#git仓库分支
label: master
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/eureka/
spring.cloud.config.discovery.enabled:true 表示开启通过服务访问config-server功能
spring.cloud.config.discovery.serviceId:hign-availability-config-server 表示指定配置中心注册到eureka的serviceId(即config-server的application-name)
八、新建GetPropertyFromConfigServerController
主要用于测试从git仓库读取配置文件内容
/**
* 测试客户端从配置服务中心获取配置文件中的内容
*
* @author weishihuai
* @date 2018/9/19 10:15
*/
@RestController
//@RefreshScope注解的作用: 如果刷新了bean,那么下一次访问bean(即执行一个方法)时就会创建一个新实例。
@RefreshScope
public class GetPropertyFromConfigServerController {
private static Logger logger = LoggerFactory.getLogger(GetPropertyFromConfigServerController.class);
@Value("${com.springcloud.wsh.message}")
String message;
@RequestMapping("/getPropertyFromConfigServer")
public String getPropertyFromConfigServer() {
String msg = "hello, i am " + message + ", i'm come from config server";
logger.info(msg);
return msg;
}
}
注意:需要加上@RefreshScope注解,主要是用于后面配置刷新用到。
//@RefreshScope注解的作用: 如果刷新了bean,那么下一次访问bean(即执行一个方法)时就会创建一个新实例。
九、测试
分别启动eureka-server、config-server,config-client项目,浏览器访问http://localhost:1111/,如图
可以看到,config-server以及config-client都成功注册到eureka。
这时我们访问 http://localhost:3333/getPropertyFromConfigServer
可以看到,我们成功从git仓库中获取到配置文件中的内容。我们可以将config-server启动多个实例,然后访问 http://localhost:3333/getPropertyFromConfigServer,可以看到成功获取配置信息,然后我们可以停掉其中一个config-server实例,我们继续访问 http://localhost:3333/getPropertyFromConfigServer,还是可以成功获取git远程仓库的配置信息,这就实现了config-server的高可用。
下面我们聊聊配置刷新的问题,在实际项目中,假如我们修改了git仓库中的配置文件的信息,这时候是不会立即生效的,下面我们先讲下手动刷新的方法,实际项目中是通过Spring Cloud Bus消息总线的方式自动刷新远程仓库配置文件,这个后续讲解。
十、改造config-client
首先我们做一个测试,我们尝试使用Git工具修改当前配置的内容,比如,将repository/config-client-prod.properties
中的com.springcloud.wsh.message的值修改为Spring Cloud Config分布式配置中心(正式生产环境)------版本2,
这时候我们访问http://localhost:3333/getPropertyFromConfigServer,
可以看到返回的配置内容还是旧的,并没有同步更新。
下面我们开始改造config-client,在config-client的pom.xml中加入监控的依赖:spring-boot-starter-actuator
<!--开启监控功能-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
acutator包含了/refresh
刷新API,我们可以调用它来实现配置文件的刷新。
a、重新启动config-client,访问一次http://localhost:3333/getPropertyFromConfigServer,可以看到当前的配置值:
b、修改Git仓库配置文件中的com.springcloud.wsh.message值
c、再次访问一次http://localhost:3333/getPropertyFromConfigServer,可以看到配置值没有改变:
d、通过POST请求发送到http://localhost:3333/refresh,这时候不能通过浏览器,注意是post请求,否则会报错
这里我们使用postman发送post请求,如下图:
我们发现,postman拦截了我们的post请求,这是因为springboot的安全拦截,由于我们需要测试是否刷新成功,我们可以在config-client的配置文件application.yml中加入
#忽略权限拦截
management:
security:
enabled: false
重启config-client,这时候我们修改一下git仓库中配置文件的值为:
com.springcloud.wsh.message=测试refresh手动刷新配置文件
接下来我们通过postman发送http://localhost:3333/refreshpost请求,
由上图说明配置文件的内容已经更新。
e、我们再次访问http://localhost:3333/getPropertyFromConfigServer,可以看到配置值已经是更新后的值
至此,我们通过actuator实现了手动刷新git远程仓库中的配置文件的内容。注意一下在config-client项目中的controller上需要加上@RefreshScope注解, 否则调用/refresh接口看不到更新的内容,笔者就是踩了这个坑,需要注意下。
十一、总结
本文主要讲解了如何实现了高可用的Config Server配置中心以及利用Actuator暴露的refresh接口来实现配置的动态更新。通过前面几篇文章的学习,我们主要学了Eureka服务注册中心、Zuul网关路由、Ribbon负载均衡、Feign声明式服务调用、Config服务配置中心,这时候我们可以抽象一个比较简单的微服务架构图:
本文是笔者在学习Spring Cloud Config的时候的一些总结、遇到的一些问题及解决方法,能力有限,仅供参考,大家共同学习,共同进步。