一、简介
在微服务项目中,服务数量和程序的配置日益增多,传统的配置文件方式已无法满足开发人员对配置管理的要求:如修改配置需要重启服务才能生效、无法支持动态调整(如日志开关、功能开关等);因此我们需要配置中心来统一管理配置。
本章节我们为微服务电商项目加入配置中心,采用SpringCloudConfig+SpringCloudBus+RabbitMq。
ok,开始实战吧。
二、准备
1、使用github存放配置文件
由于gitlab太占内存了导致实践的时候电脑有点卡,因此配置文件我们存放在github上,它们两者是类似的,使用方法也类似,当然,在实际项目中还是要放在gitlab中。
在github创建仓库shop-project-config专门用来存放配置文件;每个服务对应一个文件夹,服务名称对应文件夹名称;配置文件后缀分为dev、test、prod,分别对应开发环境、测试环境、生产环境。
其中common文件夹是各个服务共享的配置文件,这里我们配置了eureka客户端,好处是当我们的eureka服务端地址发生改变的时候,只需要修改共享配置文件就可以了,不需要修改所有eureka客户端服务的配置文件。
https://github.com/liazhan/shop-project-config/tree/37611f57b3609c82d342b4a260a70026080a4a18
版本号37611f57b3609c82d342b4a260a70026080a4a18
2、安装RabbitMq
三、在shop-basics基础上创建Module——shop-basics-cloud-config
配置中心服务端初步搭建架构如图所示
pom.xml、AppConfig、application.yml如下所示:
<?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>shop-basics</artifactId>
<groupId>com.liazhan</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>shop-basics-cloud-config</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
</project>
package com.liazhan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
/**
* @version:V1.0
* @Description: 配置中心入口类
* @author: Liazhan
* @date 2020/4/13 15:50
*/
@SpringBootApplication
@EnableConfigServer
public class AppConfig {
public static void main(String[] args) {
SpringApplication.run(AppConfig.class,args);
}
}
配置文件application.yml
server:
port: 8000
eureka:
client:
service-url:
defaultZone: http://localhost:8100/eureka/
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/liazhan/shop-project-config # 配置git仓库的地址
search-paths: common,eureka,gateway,member,weixin # git仓库地址下的相对地址,可以配置多个,用,分割。
如果我们的 Git 仓库需要权限访问,那么可以通过配置下面的两个属性来实现;
spring.cloud.config.server.git.username:访问 Git 仓库的用户名
spring.cloud.config.server.git.password:访问 Git 仓库的用户密码
启动入口类,访问http://localhost:8000/common-dev.yml
说明访问github上面的公用配置文件成功,配置中心服务端搭建成功。
四、改造除config外的其它服务为config客户端
改造之后其它服务将从配置中心读取配置。
首先改造eureka
1、添加依赖
<!-- config client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
2、添加配置文件bootstrap.yml
spring:
cloud:
config:
uri: http://localhost:8000 # 配置中心的具体地址,即 config-server
name: eureka # 对应 {application} 部分
profile: dev # 对应 {profile} 部分
label: master # 对应 {label} 部分,即 Git 的分支。如果配置中心使用的是本地存储,则该参数无用
上面这些与 Spring Cloud Config 相关的属性必须配置在 bootstrap.yml 中,config 部分内容才能被正确加载。因为 config 的相关配置会先于 application.yml,而 bootstrap.yml 的加载也是先于 application.yml。
3、删除application.yml,我们将从配置中心读取配置,之后服务配置文件只会保留bootstrap.yml
然后先启动配置中心服务端,这时候会报错找不到注册中心,我们不用管它,它会不断重试的。接着启动eureka。
访问成功,说明eureka已经成功从配置中心读取了配置,且配置中心成功注册到了注册中心,不再报错了。
改造网关gateway
1、添加依赖
<!-- config client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
2、添加配置文件bootstrap.yml
spring:
cloud:
config:
uri: http://localhost:8000 # 配置中心的具体地址,即 config-server
name: gateway,common # 对应 {application} 部分
profile: dev # 对应 {profile} 部分
label: master # 对应 {label} 部分,即 Git 的分支。如果配置中心使用的是本地存储,则该参数无用
3、删除application.yml
然后启动网关,查看注册中心
注册成功,说明已经成功从配置中心读取了配置。
改造会员服务和微信服务
1、添加依赖,不同的是,这里我们选择在shop-service-impl添加依赖,这样子模块将全部继承这个依赖。不在parent和basics添加的原因是config服务端不需要这个依赖。
<!-- config client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
2、添加配置文件bootstrap.yml
会员服务
spring:
cloud:
config:
uri: http://localhost:8000 # 配置中心的具体地址,即 config-server
name: member,common # 对应 {application} 部分
profile: dev # 对应 {profile} 部分
label: master # 对应 {label} 部分,即 Git 的分支。如果配置中心使用的是本地存储,则该参数无用
微信服务
spring:
cloud:
config:
uri: http://localhost:8000 # 配置中心的具体地址,即 config-server
name: weixin,common # 对应 {application} 部分
profile: dev # 对应 {profile} 部分
label: master # 对应 {label} 部分,即 Git 的分支。如果配置中心使用的是本地存储,则该参数无用
3、删除application.yml
分别启动微信服务和会员服务,然后访问eureka注册中心
注册成功,说明已经成功从配置中心读取了配置。
如此便完成了去除配置文件,使用配置中心统一管理配置文件。
接下来需要解决的是,配置文件的热更新。
配置文件热更新
现在如果我们修改了github存放的配置文件,服务是不会立即获取到变更的配置的,因此我们需要实现热更新。
shop-parent 添加依赖
<!--消息总线 bus-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<!--rabbitmq-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
<!--actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
shop-basics-cloud-config修改配置文件application.xml
server:
port: 8000
eureka:
client:
service-url:
defaultZone: http://localhost:8100/eureka/
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/liazhan/shop-project-config # 配置git仓库的地址
search-paths: common,eureka,gateway,member,weixin # git仓库地址下的相对地址,可以配置多个,用,分割。
bus:
enabled: true
trace:
enabled: true
rabbitmq:
host: 47.98.183.103
port: 5672
username: user
password: password
management:
endpoints:
web:
exposure:
include: "*"
由于config客户端都需要配置bus和rabbit,因此我们在github的common-dev配置文件统一配置,修改后的内容如下
eureka:
client:
service-url:
defaultZone: http://localhost:8100/eureka/
spring:
cloud:
bus:
trace:
enabled: true
enabled: true
rabbitmq:
host: 47.98.183.103
port: 5672
username: user
password: password
配置文件github地址https://github.com/liazhan/shop-project-config/tree/be262197361c1bbc43e1055e5f58ccc3e55163de
如此便完成了热更新的配置。
为了方便测试,我们修改一下微信服务和会员服务的接口
package com.liazhan.member.service.impl;
import com.liazhan.member.feign.WeiXinServiceFeign;
import com.liazhan.member.service.MemberService;
import com.liazhan.weixin.entity.TestEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @version V1.0
* @description: 会员服务接口实现类
* @author: Liazhan
* @date: 2020/4/8 0:08
*/
@RestController
@RefreshScope
public class MemberServiceImpl implements MemberService {
@Autowired
private WeiXinServiceFeign weiXinServiceFeign;
@Value("${spring.application.name}")
private String name;
@Override
public TestEntity callWeiXin() {
TestEntity test = weiXinServiceFeign.test();
test.setName(name);
return test;
}
}
package com.liazhan.weixin.service.impl;
import com.liazhan.weixin.entity.TestEntity;
import com.liazhan.weixin.service.WeiXinService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RestController;
/**
* @version V1.0
* @description:
* @author: Liazhan
* @date: 2020/4/7 23:05
*/
@RestController
@RefreshScope
public class WeiXinServiceImpl implements WeiXinService {
@Value("${spring.application.name}")
private String name;
@Override
public TestEntity test() {
return new TestEntity(name,"GuangZhou");
}
}
之后依次启动config、eureka、weixin、member服务。
访问http://localhost:8300/callWeiXin
然后我们修改github上的配置文件,将微信服务和会员服务的服务名改成liazhan-weixin222和liazhan-member222
配置文件github地址https://github.com/liazhan/shop-project-config/tree/18cf16c1eed6089dd25262dc08f63e53d7ffb8ac
修改完成之后我们可以发现会员接口和微信接口的name并没有改变。
这时候我们使用【postman】软件用post请求访问http://localhost:8000/actuator/bus-refresh/
然后再次刷新查看会员接口和微信接口的name。
可以发现name都变化了,说明配置文件热更新已经实现了。需要注意的是,由于我们的微信服务名改了,那么会员服务调用微信服务应该是调用失败才对的,为什么这里还是调用成功了呢?这里是因为eureka还保留了之前的微信服务一段时间,过一段时间之后就会剔除了,然后调用将会报错。
Webhooks
需要注意的是,这里我们修改完配置文件还要自己用post请求访问刷新接口才能实现热更新,为了省略这一步,我们可以利用Webhooks,github和gitlab都有该功能。
如上图所示,URL填写我们的刷新接口地址,但我们提交更新配置文件时,github或gitlab会自动去访问我们的刷新接口地址。
需要注意的是,我们的刷新接口地址目前是用的本地ip,这样是不会被访问到的,要么将config部署在公网ip服务器,要么使用内网穿透。内网穿透可以用ngrok,有免费的可以使用,虽然有限流等限制,不过不妨碍我们测试。具体使用自行看官网的教程,很简单。
为了方便,我们使用内网穿透,经过操作之后我的域名是http://liazhan.free.idcfengye.com,这个域名对应了我本地的127.0.0.1:8000,因此刷新接口地址为http://liazhan.free.idcfengye.com/actuator/bus-refresh/
添加Webhook之后,我们可以测试了,将微信服务和会员服务的名称改回liazhan-weixin和liazhan-member。
配置文件github地址https://github.com/liazhan/shop-project-config/tree/1efa5d983616b7ca6305e6288fdc618f4c404a3f
然后查看接口,发现name已经改回来了。
ok,大功告成。
github项目地址https://github.com/liazhan/shop-project/tree/78998cbf5d103dbe3dfdf2a7612e742cd10c44ca
版本号为78998cbf5d103dbe3dfdf2a7612e742cd10c44ca