对于传统的单体应用而言,常使用配置文件来管理所有配置,
比如SpringBoot的application.yml文件,但是在微服务架构中全部手动修改的话很麻烦而且不易维护。
微服务的配置管理一般有以下需求:
综上所述对于微服务架构而言,一套统一的,通用的管理配置机制是不可缺少的总要组成部分。常见的做法就是通过配置服务器进行管理。
Spring Cloud Config
为分布式系统中的外部配置提供服务器和客户端支持。
Apollo
(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
Disconf
专注于各种「分布式系统配置管理」的「通用组件」和「通用平台」, 提供统一的「配置管理服务」包括 百度、滴滴出行、银联、网易、拉勾网、苏宁易购、顺丰科技 等知名互联网公司正在使用!「disconf」在「2015 年度新增开源软件排名 TOP 100(OSC开源中国提供)」中排名第16强。
Spring Cloud Config项目是一个解决分布式系统的配置管理方案。
它包含了Client和Server两个部分,server提供配置文件的存储、以接口的形式将配置文件的内容提供出去,client通过接口获取数据、并依据此数据初始化自己的应用。
Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持。
使用Config Server,您可以为所有环境中的应用程序管理其外部属性。
它非常适合spring应用,也可以使用在其他语言的应用上。
随着应用程序通过从开发到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切。
服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具。
Spring Cloud Config服务端特性:
Config Server是一个可横向扩展、集中式的配置服务器,它用于集中管理应用程序各个环境下的配置,默认使用Git存储配置文件内容,也可以使用SVN存储,或者是本地文件存储。
这里使用git作为学习的环境。
使用GitHub时,国内的用户经常遇到的问题是访问速度太慢,有时候还会出现无法连接的情况。
如果我们希望体验Git飞一般的速度,可以使用国内的Git托管服务——码云(gitee.com)。
和GitHub相比,码云也提供免费的Git仓库。此外,还集成了代码质量检测、项目演示等功能。
对于团队协作开发,码云还提供了项目管理、代码托管、文档管理的服务。
server:
port: 9001 #端口
spring:
application:
name: service-product #服务名称
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=utf8
username: root
password: root
jpa:
database: MySQL
show-sql: true
open-in-view: true
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向组成中心注册服务ID
lease-renewal-interval-in-seconds: 5 #向注册中心中注册服务id
lease-expiration-duration-in-seconds: 10 #续约到期的时间
name: itbluebox
@RestController
@RequestMapping("/product")
public class ProductController {
@Autowired
private ProductService productService;
@Value("${server.port}")
private String port;
@Value("${spring.cloud.client.ip-address}")
private String ip;
@Value(value = "${name}")
private String name;
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Product findById(@PathVariable Long id) {
Product product = productService.findByID(id);
product.setProductName("访问的服务地址:"+ip+":"+port);
return product;
}
@RequestMapping(value = "/test")
public String test(){
return name;
}
}
创建成功
文件命名规则:
{application}-{profile}.yml
{application}-{profile}.properties
application
为应用名称 profile指的开发环境(用于区分开发环境,测试环境、生产环境等)将上述文件移动到电脑桌面并,对文件重新命名修改配置文件product-pro.yml
server:
port: 9002 #端口
spring:
application:
name: service-product #服务名称
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=utf8
username: root
password: root
jpa:
database: MySQL
show-sql: true
open-in-view: true
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向组成中心注册服务ID
lease-renewal-interval-in-seconds: 5 #向注册中心中注册服务id
lease-expiration-duration-in-seconds: 10 #续约到期的时间
name: itbluebox-pro
将上述文件移动到电脑桌面并,创建新的配置文件product-dev.yml
server:
port: 9001 #端口
spring:
application:
name: service-product #服务名称
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=utf8
username: root
password: root
jpa:
database: MySQL
show-sql: true
open-in-view: true
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向组成中心注册服务ID
lease-renewal-interval-in-seconds: 5 #向注册中心中注册服务id
lease-expiration-duration-in-seconds: 10 #续约到期的时间
name: itbluebox-dev
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class,args);
}
}
在这之前复制一下Git请求的服务器的地址
server:
port: 10001 #服务端口
spring:
application:
name: config-server #指定服务名
cloud:
config:
server:
git:
uri: https://gitee.com/itbluebox/config-repostory.git
运行成功
访问测试:http://localhost:10001/product-dev.yml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
springboot的应用配置文件,需要通过Config-server获取,这里不再需要。
spring:
cloud:
config:
name: product #应用名称需要对应Git中配置文件的名称的前半部分
profile: dev #开发环境
label: master #git当中的分支
uri: http://localhost:10001 #config-server的请求地址
访问:http://localhost:9001/product/1
访问:http://localhost:9001/product/test
将dev修改为pro
spring:
cloud:
config:
name: product #应用名称需要对应Git中配置文件的名称的前半部分
profile: pro #开发环境
label: master #git当中的分支
uri: http://localhost:10001 #config-server的请求地址
重新启动运行
请求的端口改变了
访问:http://localhost:9002/product/1
我们已经在客户端取到了配置中心的值,
修改Gitee上的值
修改内容
访问:http://localhost:9002/product/test
但当我们修改Gitee上面的值时,
服务端(Config Server)能实时获取最新的值,但客户端(Config Client)读的是缓存,无法实时获取最新值。
SpringCloud已经为我们解决了这个问题,那就是客户端使用post去触发refresh,获取最新数据,需要依赖spring-boot-starter-actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
ProductController
类加上@RefreshScope
@RestController
@RequestMapping("/product")
@RefreshScope //代表的是开启动态刷新
public class ProductController {
@Autowired
private ProductService productService;
@Value("${server.port}")
private String port;
@Value("${spring.cloud.client.ip-address}")
private String ip;
@Value(value = "${name}")
private String name;
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Product findById(@PathVariable Long id) {
Product product = productService.findByID(id);
product.setProductName("访问的服务地址:"+ip+":"+port);
return product;
}
@RequestMapping(value = "/test")
public String test(){
return name;
}
}
bootstrap.yml
中开发端点# 开启动态刷新的请求路径的端点
management:
endpoints:
web:
exposure:
include: refresh
访问:http://localhost:9002/product/test
其值itbluebox-product改变因为重新启动了
我们再次修改Gitee对应的配置文件的值
提交并保存
再次访问:http://localhost:9002/product/test
访问:http://localhost:9002/actuator/refresh
再次访问:http://localhost:9002/product/test
在之前的代码中,客户端都是直接调用配置中心的server端来获取配置文件信息。
这样就存在了一个问题,客户端和服务端的耦合性太高,如果server端要做集群,客户端只能通过原始的方式来路由,server端改变IP地址的时候,客户端也需要修改配置,不符合springcloud服务治理的理念。
springcloud提供了这样的解决方案,我们只需要将server端当做一个服务注册到eureka中,client端去eureka中去获取配置中心server端的服务既可。
<!--引入EurekaClient-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向组成中心注册服务ID
lease-renewal-interval-in-seconds: 5 #向注册中心中注册服务id
lease-expiration-duration-in-seconds: 10 #续约到期的时间
这样server端的改造就完成了。
先启动eureka注册中心,在启动server端,
在浏览器中访问:
复制一份ConfigServerApplication
修改一下配置文件的端口号
访问Eurekahttp://localhost:9000/
修改配置文件
spring:
cloud:
config:
name: product #应用名称需要对应Git中配置文件的名称的前半部分
profile: pro #开发环境
label: master #git当中的分支
#uri: http://localhost:10001 #config-server的请求地址
#通过注册中心去获取config-server配置
discovery:
enabled: true #开启服务发现
service-id: config-server
# 开启动态刷新的请求路径的端点
management:
endpoints:
web:
exposure:
include: refresh
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向组成中心注册服务ID
重新启动
访问测试:http://localhost:9002/product/1
在微服务架构中,
通常会使用轻量级的消息代理来构建一个共用的消息主题来连接各个微服务实例,
它广播的消息会被所有在注册中心的微服务实例监听和消费,也称消息总线。
SpringCloud中也有对应的解决方案,
SpringCloud Bus 将分布式的节点用轻量的消息代理连接起来,
可以很容易搭建消息总线,
配合SpringCloud config 实现微服务应用配置信息的动态更新。
根据此图我们可以看出利用Spring Cloud Bus做配置更新的步骤:
刚刚在上述已经引入了对应消息总线的依赖,在这里是做介绍
server:
port: 10001 #服务端口
spring:
application:
name: config-server #指定服务名
cloud:
config:
server:
git:
uri: https://gitee.com/itbluebox/config-repostory.git
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
management:
endpoints:
web:
exposure:
include: bus-refresh
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向组成中心注册服务ID
lease-renewal-interval-in-seconds: 5 #向注册中心中注册服务id
lease-expiration-duration-in-seconds: 10 #续约到期的时间
<!--消息总线的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
spring:
cloud:
config:
name: product #应用名称需要对应Git中配置文件的名称的前半部分
profile: pro #开发环境
label: master #git当中的分支
#uri: http://localhost:10001 #config-server的请求地址
#通过注册中心去获取config-server配置
discovery:
enabled: true #开启服务发现
service-id: config-server
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向组成中心注册服务ID
修改product-pro.yml
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
提交并保存
将之前的ConfigServerApplication1 :10002/关闭
重新启动对应的eureka-server , config-server , product-service。
配置信息刷新后,只需要向配置中心发送对应的请求,即可刷新每个客户端的配置。
访问测试:http://localhost:9002/product/1
访问:http://localhost:9002/product/test
这个时候修改Gitee当中product-pro.yml 的内容
提交保存后再次访问http://localhost:9002/product/test
我们发现并没有改变
向http://localhost:10001/actuator/bus-refresh,发送POST请求
然后启动RabbitMQ
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_44757034/article/details/121952177
内容来源于网络,如有侵权,请联系作者删除!