服务配置和服务总线
Nacos可以替换Eureka、Config、Bus
一、分布式配置中心(Config)
概述
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能够运行,所以一套集中式的,动态的配置管理设施是必不可少的。
SpringCloud提供了ConfigServer来解决这个问题,我们每一个微服务自己带着一个application.yml,上百个配置文件的管理......
服务端也称分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访问接口。
客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息,配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容。
可以做什么:
- 集中管理配置文件
- 不同环境不同配置,动态化的配置更新,分环境部署比如dev/test/prod/beta/release
- 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息
- 当配置发生变动时,服务不需要重启即可感知到配置的变化并应用新的配置
- 将配置信息以REST接口的形式暴露
可以与GitHub整合配置
官网:https://spring.io/projects/spring-cloud-config
服务端配置与测试
在Github【打不开用getee】上新建一个名为sprincloud-config的新Repository
克隆地址:https://gitee.com/jiaoyuliang/sprincloud-config.git
git bash命令: git clone [地址]
(1)新建模块cloud-config-center-3344
(2)pom
<!-- Config -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
(3)yml
server:
port: 3344
spring:
application:
name: cloud-config-center
cloud:
config:
server:
git:
uri: git@gitee.com:jiaoyuliang/sprincloud-config.git #Gitee:SSH的连接
search-paths:
- springcloud-config #搜索目录
label: master #读取分支
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
(4)主启动类
package com.jiao.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
/**
* @author jyl
* @create 2021-3-9
*/
@SpringBootApplication
@EnableConfigServer
public class ConfigCenterMain3344 {
public static void main(String[] args) {
SpringApplication.run(ConfigCenterMain3344.class,args);
}
}
(5)windows下修改hosts文件,增加映射
(6)测试通过Config微服务是否可以从Gitee上获取配置信息
在Gitee新建三个配置文件:
在本地可以下载更新:
采用SSH的话需要在Gitee设置公钥,并且添加配置,这里采用http连接访问测试:(启动7001、3344端口)
...
#uri: git@gitee.com:jiaoyuliang/sprincloud-config.git #Gitee:SSH的连接
uri: https://gitee.com/jiaoyuliang/sprincloud-config.git #http连接
...
配置文件读取规则:
- /{label}/{application}-{profile}.yml
http://config-3344.com:3344/master/config-dev.yml
- /{application}-{profile}.yml
http://config-3344.com:3344/config-dev.yml
- /{application}/{profile}[/{label}]
http://config-3344.com:3344/config/dev/master
- 重要配置细节总结
客户端配置与测试
(1)新建模块:cloud-config-client-3355
(2)pom
<!-- Config -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
(3)bootstrap.yml
- application.yml是用户级的资源配置
- bootstrap.yml是系统级的,优先级高
Spring Cloud会创建一个“Bootstrap Context”,作为Spring应用的“Application Context”的父上下文。初始化的时候,“Bootstrap Context”负责从外部源加载配置属性并解析配置。这两个上下文共享一个外部获取的“Environment”。
“Bootstrap”属性有高优先级,默认情况下,它们不会被本地配置覆盖。“Bootstrap Context”和“Application Context”有着不同的约定,所以新增了一个“bootstrap.yml”文件,保证“Bootstrap Context”和“Application Context”配置分离。
将Client模块(3355)下的application.yml文件改为bootstrap.yml这是很关键的,因为bootstrap.yml比application.yml先加载,优先级更高。
server:
port: 3355
spring:
application:
name: config-client
cloud:
config:
label: master #分支名称
name: config #配置文件名称
profile: dev #读取后缀名称
uri: http://localhost:3344 #配置中心地址
eureka:
client:
service-url:
defaultZone: htttp://localhost:7001/eureka
(4)修改config-dev.yml配置并提交到Gitee,比如加个变量age或者版本号version
(5)主启动
package com.jiao.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @author jyl
* @create 2021-3-9
*/
@SpringBootApplication
@EnableEurekaClient
public class ConfigClientMain3355 {
public static void main(String[] args) {
SpringApplication.run(ConfigClientMain3355.class,args);
}
}
(6)业务类
package com.jiao.springcloud.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 ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping(value = "/configInfo")
public String getConfigInfo(){
return configInfo;
}
}
(7)测试(依次启动7001、3344、3355)要连网访问Gitee哦~~~
http://config-3344.com:3344/master/config-dev.yml
http://localhost:3355/configInfo
出现的问题:Gitee修改版本号,3344访问立即改变,但是3355访问不会立即改变(需要重启3355才会改变)。
解决:不重启、3355的动态刷新。
客户端之动态刷新
修改3355模块:
(1)pom增加actuator监控
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
(2)修改yml,暴露监控端口
...
#暴露监控端口
management:
endpoints:
web:
exposure:
include: "*"
(3)@RefreshScope业务类Controller修改
(4)此时修改Gitee----》3344----》3355
- 启动7001、3344后修改Gitee的dev版本为2,(3344立即访问为2);
- 再启动3355,立即访问版本为2;
- 这里并没有成功!
- (7001、3344、3355不关闭的前提下)把Gitee的dev版本修改为3;
- 3344立即访问为版本3,而3355立即访问为2,动态更新失败!
解决:测试人员发送post请求刷新3355,
curl -X POST "http://localhost:3355/actuator/refresh"
二、消息总线(Bus)
概述
对Config的加深,分布式自动刷新配置功能。Config+Bus实现配置的动态刷新。
Bus支持两种消息代理:RabbitMQ和Kafka。
用来将分布式系统的节点与轻量级消息系统连接起来的框架,它整合了Java的事件处理机制和消息中间件的功能。
做什么:管理和传播分布式系统间的消息,就像一个分布式执行器,可用于广播状态更改、事件推送等,也可以当做微服务间的通信通道。
- 什么是总线:
在微服务架构的系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线。在总线上的各个实例,都可以方便的广播一些需要让其他连接在该主题上的实例都知道的消息。
- 基本原理:
ConfigClient 实例都监听MQ中同一个topic(默认是springcloubus),当一个服务刷新数据的时候,它会把这个信息放入到Topic中,这样其他监听统一topic的服务就能得到通知,然后去更新自身的配置。
尚硅谷ActiveMQ教程(MQ消息中间件快速入门):https://www.bilibili.com/video/av55976700?fromsearch&seid=15010075915728605208
RabbitMQ环境配置
- 安装Erlang,下载地址:
http://erlang.org/download/otp_win64_21.3.exe(cmd:erl -version 测试安装和环境变量是否成功)
- 安装RabbitMQ,下载地址:
https://dl.bintray.com/rabbitmq/all/rabbitmq-server/3.7.14/rabbitmq-server-3.7.14.exe(在sbin下的cmd:rabbitmq-service start,再rabbitmq-plugins enable rabbitmq_management)
测试:http://localhost:15672,账号/密码:guest/guest(访问没问题下面几步可忽略。)
- 进入RabbitMQ安装路径下的sbin目录:
- 输入以下命令启动管理功能:
D:\application\RabbitMQServer\rabbitmq_server-3.7.14\sbin>下:
rabbitmq-plugins enable rabbitmq_management
- 访问地址查看是否安装成功:
- 输入账号密码并登录:guest guest
动态刷新全局广播
- 必须先具备良好的RabbitMQ环境先
- 演示广播效果,增加复杂度,再以3355为模板再制作一个3366
yml端口号改一下。
主启动类:
package com.jiao.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @author jyl
* @create 2021-3-12
*/
@SpringBootApplication
@EnableEurekaClient
public class ConfigClientMain3366 {
public static void main(String[] args) {
SpringApplication.run(ConfigClientMain3366.class,args);
}
}
controller:
package com.jiao.springcloud.controller;
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;
@RestController
@RefreshScope
public class ConfigClientController {
@Value("${server.port}")
private String serverPort;
@Value("${config.info}")
private String configInfo;
@GetMapping(value = "/configInfo")
public String getConfigInfo(){
return "serverPort: "+serverPort+"\t\n\n configInfo: "+configInfo;
}
}
- 设计思想
- 利用消息总线触发一个客户端/bus/refresh,而刷新所有客户端的配置。(不适合)
- 利用消息总线触发一个服务端ConfigServer的/bus/refresh端点,而刷新所有客户端的配置。(适合)
- cloud-config-center-3344配置中心服务端添加消息总线支持
pom:
<!-- 添加消息总线RabbitMQ支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
yml:
...spring下
#rabbitmq相关配置
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
...
#rabbitmq相关配置,暴露bus刷新配置的端点
management:
endpoints:
web:
exposure:
include: 'bus-refresh'
- cloud-config-client-3355客户端添加消息总线支持
pom同上加的部分
yml只用加host、port、username....这个就可以。
- cloud-config-client-3366客户端添加消息总线支持
pom同上加的部分
yml只用加host、port、username....这个就可以。
- 测试(7001 3344 3355 3366)
发送post请求:curl -X POST "http://localhost:3344/actuator/bus-refresh"
http://config-3344.com:3344/config-dev.yml
http://localhost:3355/configInfo
http://localhost:3366/configInfo
- 一次修改,广播通知,处处生效
动态刷新定点通知
不想全部通知,只想定点通知:通知3355、不通知3366。
公式 : http://localhost:配置中心的端口号/actuator/bus-refresh/{destination}
举例:curl -X POST "http://localhost:3344/actuator/bus-refresh/config-client:3355"
回顾: