前言
本文目录
准备工作
本文最终代码gitee地址
- 学习本文需要rabbitmq的知识基础(rabbitmq文章)
- git知识(可以看廖雪峰的文章)
- eureka知识(eureka文章)
什么是配置中心
配置中心概述
对于传统的单体应用而言,常使用配置文件来管理所有配置,比如SpringBoot的application.yml文件,
但是在微服务架构中全部手动修改的话很麻烦而且不易维护。微服务的配置管理一般有以下需求:
- 集中配置管理,一个微服务架构中可能有成百上千个微服务,所以集中配置管理是很重要的。
- 不同环境不同配置,比如数据源配置在不同环境(开发,生产,测试)中是不同的。
- 运行期间可动态调整。例如,可根据各个微服务的负载情况,动态调整数据源连接池大小等
- 配置修改后可自动更新。如配置内容发生变化,微服务可以自动更新配置
综上所述对于微服务架构而言,一套统一的,通用的管理配置机制是不可缺少的总要组成部分。常见的 做法就是通过配置服务器进行管理。
常见配置中心
Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持。(本文讲解)
Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的
配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置 管理场景。
Disconf 专注于各种「分布式系统配置管理」的「通用组件」和「通用平台」, 提供统一的「配置管理 服务」包括
百度、滴滴出行、银联、网易、拉勾网、苏宁易购、顺丰科技 等知名互联网公司正在使用! 「disconf」在「2015 年度新增开源软件排名
TOP 100(OSC开源中国提供)」中排名第16强。
Spring Cloud Config简介
Spring Cloud Config项目是一个解决分布式系统的配置管理方案。它包含了Client和Server两个部分, server提供配置文件的存储、以接口的形式将配置文件的内容提供出去,client通过接口获取数据、并 依据此数据初始化自己的应用。
原理图:
Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持。使用Config Server,您可
以为所有环境中的应用程序管理其外部属性。它非常适合spring应用,也可以使用在其他语言的应用
上。随着应用程序通过从开发到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用
程序具有迁移时需要运行的一切。服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置
环境,以及可以访问用于管理内容的各种工具。
Spring Cloud Config服务端特性:
- HTTP,为外部配置提供基于资源的API(键值对,或者等价的YAML内容)
- 属性值的加密和解密(对称加密和非对称加密)
- 通过使用
@EnableConfigServer
在Spring boot应用中非常简单的嵌入。 - Config客户端的特性(特指Spring应用)
- 绑定Config服务端,并使用远程的属性源初始化Spring环境。
- 属性值的加密和解密(对称加密和非对称加密)
Spring Cloud Config项目搭建
准备工作
Config Server是一个可横向扩展、集中式的配置服务器,它用于集中管理应用程序各个环境下的配置, 默认使用Git存储配置文件内容,也可以使用SVN存储,或者是本地文件存储。这里使用git作为学习的 环境
创建远程仓库
创建一个远程仓库存放项目的配置文件(过程省略)
注意要创建一个公开的仓库,私有仓库后续配置文件需要指定用户名以及密码!!!
如下图:
然后新建一个产品模块文件夹如下:
上传产品微服务配置文件(开发、生产以及测试环境)
搭建SpringCloud Config服务端项目
创建项目
过程省略(如下图)
引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
</dependencies>
配置启动类
package cn.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class,args);
}
}
注:@EnableConfigServer
: 通过此注解开启注册中心服务端功能
配置application.yml
server:
port: 10005
spring:
application:
name: springCloud-configServer
cloud:
config:
server:
git:
uri: https://gitee.com/lxl088/blog_cloud-config.git
default-label: master #使用master分支
basedir: D:/springCloud/config/git
logging:
level:
cn: DEBUG
注:
通过 spring.cloud.config.server.git.uri
: 配置git服务地址
通过spring.cloud.config.server.git.username
: 配置git用户名
通过spring.cloud.config.server.git.password
: 配置git密码
default-label
指定使用的分支
basedir
指从git远程仓库拉取下来文件后,保存到本地的位置
如果构建的远程仓库是公开的,则不需要指定用户名以及密码
测试
查看效果
启动此微服务,可以在浏览器上,通过server端访问到git服务器上的文件
http://localhost:10005/product-dev.yml
访问测试
本地查看
上面配置文件中我们配置的路径basedir: D:/springCloud/config/git
,就是config服务端抓取gitee到本地的位置,可以看到
修改配置文件
此时我们在gitee上直接修改文件,如下:
发现本地文件也相继更新
刷新页面,发现配置文件也相继更新
搭建客户端程序
创建项目
过程省略
引入依赖
<!--因为要启动web服务,做测试-->
<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>
<version>2.1.0.RELEASE</version>
</dependency>
添加bootstrap.yml
使用加载级别更高的 bootstrap.yml(优先于application.yml)文件进行配置。启动应用时会检查此配置文件,在此文件中指定配置中心的服务地址。会自动的拉取所有应用配置并启用
spring:
cloud:
config:
uri: http://localhost:10005 # 非高可用
name: product #前缀
profile: dev #后缀
label: master
uri:对应服务端配置的地址以及端口
配置启动类
package cn.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class,args);
}
}
写一个测试的controller
package cn.config.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ConfigController {
@Value("${config-file}")
String config_msg;
@GetMapping("/getConfig")
public String getConfig(){
return config_msg;
}
}
config-file就是之前我们写在配置文件中的一个键值对。
启动服务
服务启动
然后发送请求,查看config-file的值是否获取到了
修改配置文件
修改gitee上面的配置文件如下:
然后再次请求如下:
发现配置文件并没有及时的更新。
并且本地的该文件同样是没有更新的,此时我们直接请求服务端的地址,查看该配置文件
发现不但请求地址的配置文件是最新的,而且本地的配置文件也被重新抓取更新。
那么这是为什么呢???
实现客户端的手动更新
因为每次请求服务端的地址时,服务端都会拉取最新的文件到本地,客户端在启动时拿到了最新的配置文件,但是客户端启动之后,配置文件更改,由于客户端并没有重启,所以拿到的还是之前的配置文件。
打个比如:一个web服务端口设置为8080,然后启动,之后你修改application.yml的配置文件为端口为9090,但是这个已经启动的web服务仍然还是以8080的端口启动着。
那么如何使得修改后的配置文件生效呢?
其实就是一句话 重启。
你重启该服务,服务重新加载配置文件。
只是springcloud提供了一种更优雅的方式重启服务,不是向之前一样,点击服务启动,而是通过发送一个post请求来重启该服务。
改造项目
在客户端的项目中引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
发现这不是健康检查的jar包吗?对就是它。
- 修改文件配置
management:
endpoints:
web:
exposure:
include: '*'
- 给controller添加注解
注意一定要加上该注解,不然不生效
重启服务
重启客户端服务
然后访问请求
然后修改配置文件
再次请求
发现并没有更新,那肯定啊,你还没有重启呢!打开健康检查的地址:
之后打开postman发送这个请求(Post的方式)发送请求之后
看到提示信息,此时看客户端服务的控制台,发现已经重启服务了(图略)。此时再次请求服务,发现已经完成更新!!!
但是这样一个一个的刷新,之后万一有很多个微服务,那挨个重启也太麻烦了,那么如何解决呢?接着看
配置中心的高可用
在之前的代码中,客户端都是直接调用配置中心的server端来获取配置文件信息。这样就存在了一个问题,客户端和服务端的耦合性太高,如果server端要做集群,客户端只能通过原始的方式来路由,server端改变IP地址的时候,客户端也需要修改配置,不符合springcloud服务治理的理念。
上面总结一句话就是 高可用配置中心
springcloud提供了这样的解决方案,我们只需要将server端当做一个服务注册到eureka中,client端去eureka中去获取配置中心server端的服务既可。
服务端改造
搭建一个eureka注册中心的项目
具体内容可以看之前的文章
Eureka文章地址
创建过程略
因为涉及到eureka,所以要在创建一个eureka的项目,我直接拿之前的来用了,也很简单
启动如下:
接着来改造服务端 配置中心
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
修改配置文件
添加如下配置
# Eureka配置
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:6001/eureka/,http://127.0.0.1:6002/eureka/
instance:
lease-expiration-duration-in-seconds: 10 #eureka client 发送心跳给server端,续约到期时间(默认90秒)
lease-renewal-interval-in-seconds: 5 #发送心跳续约时间间隔
instance-id: ${spring.cloud.client.ip-address}:${server.port}
重启服务端服务
服务注册详情
此时服务端改造完成
客户端改造
添加依赖
<!--eureka注册-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
配置文件
spring:
cloud:
config:
# uri: http://localhost:10005 # 非高可用
name: product #前缀
profile: dev #后缀
label: master
discovery:
service-id: springCloud-configServer #注意这个服务id就是配置中心的spring.application.name
enabled: true #从eureka中获取配置中心信息
# 开启健康检查的端口
management:
endpoints:
web:
exposure:
include: '*'
# eureka注册
eureka:
client:
healthcheck: true #开启健康检查(依赖spring-boot-actuator)
service-url:
defaultZone: http://127.0.0.1:6001/eureka/,http://127.0.0.1:6002/eureka/
instance:
#prefer-ip-address: true #使用ip地址注册
lease-expiration-duration-in-seconds: 10 #eureka client 发送心跳给server端,续约到期时间(默认90秒)
lease-renewal-interval-in-seconds: 5 #发送心跳续约时间间隔
instance-id: ${spring.cloud.client.ip-address}:${server.port}
重启服务
重启客户端服务
再次请求服务,如下:
高可用改造结束!!!
消息总线bus
之前我们说了修改配置后,需要挨个Post请求,重启服务很麻烦,我们可以通过消息总线解决这个问题。
在微服务架构中,通常会使用轻量级的消息代理来构建一个共用的消息主题来连接各个微服务实例,它广播的消息会被所有在注册中心的微服务实例监听和消费,也称消息总线。
SpringCloud中也有对应的解决方案,SpringCloud Bus 将分布式的节点用轻量的消息代理连接起来,可以很容易搭建消息总线,配合SpringCloud config 实现微服务应用配置信息的动态更新。
原理图
根据此图我们可以看出利用Spring Cloud Bus做配置更新的步骤:
- 提交代码触发post请求给bus/refresh
- server端接收到请求并发送给Spring Cloud Bus
- Spring Cloud bus接到消息并通知给其它客户端
- 其它客户端接收到通知,请求Server端获取最新配置
- 全部客户端均获取到最新的配置
消息总线整合配置中心
因为消息总线依赖rabbitmq,所以需要启动rabbitmq(rabbitmq的文章)
引入依赖
向配置中心服务端添加依赖
<!--健康检查-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--消息总线提供分发重启服务的功能-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<!--rabbit作为消息中间件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
修改配置
server:
port: 10005
spring:
application:
name: springCloud-configServer
cloud:
config:
server:
git:
uri: https://gitee.com/lxl088/blog_cloud-config.git
default-label: master #使用master分支
basedir: D:/springCloud/config/git
search-paths: test
rabbitmq:
port: 5672
host: localhost
username: guest
password: guest
# 健康检查
management:
endpoints:
web:
exposure:
include: '*'
logging:
level:
cn: DEBUG
# Eureka配置
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:6001/eureka/,http://127.0.0.1:6002/eureka/
instance:
lease-expiration-duration-in-seconds: 10 #eureka client 发送心跳给server端,续约到期时间(默认90秒)
lease-renewal-interval-in-seconds: 5 #发送心跳续约时间间隔
instance-id: ${spring.cloud.client.ip-address}:${server.port}
客户端添加依赖
<!--总线-->
<!--总线-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<!--配置中心-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
修改客户端的配置
注意要修改客户端码云上的配置(rabbitmq的配置)
然后分别重启服务端和客户端的服务,如下:
此时我们去找下总线重启服务的地址,如下:
测试
修改
此时我们请求查看下
之后总线请求重启服务
同样是Post请求
此时再次请求,如下
配置已经完成更新
至此本文结束,谢谢观看。本文代码源码