概述
• Spring Cloud Config 解决了在分布式场景下多环境配置文件的管理和维护。
• 好处:
• 集中管理配置文件
• 不同环境不同配置,动态化的配置更新
• 配置信息改变时,不需要重启即可更新配置信息到服务
Bus 概述
• Spring Cloud Bus 是用轻量的消息中间件将分布式的节点连接起来,可以用于广播配置文件的更改或者服务的监控管理。关键的思想就是,消息总线可以为微服务做监控,也可以实现应用程序之间相通信。
• Spring Cloud Bus 可选的消息中间件包括 RabbitMQ 和 Kafka 。
RabbitMQ
RabbitMQ 提供了 6 种工作模式:简单模式、work queues、Publish/Subscribe 发布与订阅模式、Routing
路由模式、Topics 主题模式、RPC 远程调用模式(远程调用,不太算 MQ;暂不作介绍)。
步骤:
<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.0modelVersion>
<groupId>com.fsgroupId>
<artifactId>study-springcloudartifactId>
<version>1.0-SNAPSHOTversion>
<modules>
<module>fs-server-eureka-7001module>
<module>fs-config-servermodule>
<module>fs-config-provider-8001module>
<module>fs-config-provider-8002module>
<module>fs-stream-RabbitMQ-provider-8801module>
<module>fs-stream-RabbitMQ-consumer-9901module>
modules>
<packaging>pompackaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>2.3.2.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Hoxton.SR6version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2.2.1.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
<version>2.2.4.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
<version>2.2.4.RELEASEversion>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.20version>
<scope>runtimescope>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.20version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.3.2version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.12version>
dependency>
dependencies>
dependencyManagement>
<dependencies>
dependencies>
project>
<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>study-springcloudartifactId>
<groupId>com.fsgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>fs-config-serverartifactId>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bus-amqpartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-config-serverartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
dependencies>
project>
server:
port: 3344
spring:
application:
name: fs-config-server
cloud:
# 配置git远程厂库地址
config:
server:
git:
uri: https://gitee.com/xiaofugitee/springcloud-config.git # 码云仓库地址
# 搜索目录
# search-paths:
# - springcloud-config #仓库名字
# username: xiaofuGitee
# password: ***********
# 跳过ssl验证
# skip-ssl-validation: true
# 读取分支
label: master
# RabbitMQ相关配置
rabbitmq:
host: 192.168.93.132
port: 5672
username: root
password: root
virtual-host: /
#服务注册到eureka
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka #,http://fseureka7002.com:7002/eureka,http://fseureka7003.com:7003/eureka
# 暴露bus刷新配置的端点,使用bus,只需要在config server中配置就可以
management:
endpoints:
web:
exposure:
include: 'bus-refresh' # 使用bus发送刷新的post请求
# 由于配置了bus消息,gitee上的配置文件进行更改,只需要发送一个3344post请求 处处生效3355,3366的配置都会进行更新,
# curl -X POST "http://localhost:3344/actuator/bus-refresh"
//开启作为配置中心
@EnableConfigServer
package com.fs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
//开启作为配置中心
@EnableConfigServer
public class ConfigServer3344 {
public static void main(String[] args) {
SpringApplication.run(ConfigServer3344.class,args);
}
}
8001与8002 代码一模一样,只是bootstrap的server.port端口一个是8001,一个是8002
<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>study-springcloudartifactId>
<groupId>com.fsgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>fs-config-provider-8001artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bus-amqpartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-configartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
dependencies>
project>
server:
port: 8001
spring:
application:
name: fs-config-provider
cloud:
config:
label: master # 分支名称
name: config # 配置文件前缀名 - 前面的名称
profile: dev # 读取后缀名 就是读取码云仓库master分支下的config-dev.yml配置文件
# uri: http://localhost:3344 # 配置中心地址
# 从eureka中发现configserver的服务的uri 这里写了,就不用写uri了
discovery:
enabled: true # 是否从注册中心获取信息
service-id: fs-config-server # 服务名称
# RabbitMQ相关配置
rabbitmq:
host: 192.168.93.132
port: 5672
username: root
password: root
virtual-host: /
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka #,http://fseureka7002.com:7002/eureka,http://fseureka7003.com:7003/eureka
# 暴露bus刷新配置的端点 才能动态刷新配置,使用bus,只需要在config server中配置就可以
#management:
# endpoints:
# web:
# exposure:
# include: 'bus-refresh'
# include: '*' #暴露所有
package com.fs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class ConfigProvider8001 {
public static void main(String[] args) {
SpringApplication.run(ConfigProvider8001.class,args);
}
}
@RefreshScope//配置刷新功能
//cmd手动刷新才能获取到最新的配置信息 curl -X POST “http://localhost:8001/actuator/refresh”
//但是使用了BUS消息总线后,只需要在configserver中发送一次请求,所有绑定的微服务,都会被广播到,
// 就不需要每个微服务都去发送请求,来获取最新的配置信息
package com.fs.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//配置刷新功能
//cmd手动刷新才能获取到最新的配置信息 curl -X POST "http://localhost:8001/actuator/refresh"
//但是使用了BUS消息总线后,只需要在configserver中发送一次请求,所有绑定的微服务,都会被广播到,
// 就不需要每个微服务都去发送请求,来获取最新的配置信息
public class ConfigProviderController {
@Value("${server.port}")
private String serverPort;
//获取云(git) 上的配置文件信息,来确保我们的的服务是否获取到最新的
@Value("${config.info}")
private String configInfo;
//输出一下最新的配置信息
@GetMapping("/configInfo")
public String getConfigInfo(){
return "serverPort:"+serverPort+"~~~configInfo:"+configInfo;
}
}
依次启动:
1.fs-server-eureka-7001
2.fs-config-server
启动configserver报错,不管,实际上是连接到了的
org.eclipse.jgit.api.errors.TransportException: https://gitee.com/xiaofugitee/springcloud-config.git: Secure connection to https://gitee.com/xiaofugitee/springcloud-config.git could not be stablished because of SSL problems
3.fs-config-provider-8001
4,fs-config-provider-8002
http://localhost:3344/config-dev.yml
http://localhost:8001/configInfo
http://localhost:8002/configInfo
http://localhost:3344/config-dev.yml
http://localhost:8001/configInfo
http://localhost:8002/configInfo
由于配置了bus消息,gitee上的配置文件进行更改,只需要发送一个3344post请求 处处生效3355,3366的配置都会进行更新,
** curl -X POST http://localhost:3344/actuator/bus-refresh **
http://localhost:3344/config-dev.yml
http://localhost:8001/configInfo
http://localhost:8002/configInfo
• Spring Cloud Stream 是一个构建消息驱动微服务应用的框架。
• Stream 解决了开发人员无感知的使用消息中间件的问题,因为Stream对消息中间件的进一步封装,可以做
到代码层面对中间件的无感知,甚至于动态的切换中间件,使得微服务开发的高度解耦,服务可以关注更多
自己的业务流程。
• Spring Cloud Stream目前支持两种消息中间件RabbitMQ和Kafka
• Spring Cloud Stream 构建的应用程序与消息中间件之间是通过绑定器 Binder
相关联的。绑定器对于应用程序而言起到了隔离作用, 它使得不同消息中间件
的实现细节对应用程序来说是透明的。
• binding 是我们通过配置把应用和spring cloud stream 的 binder 绑定在一起
• output:发送消息 Channel,内置 Source接口
• input:接收消息 Channel,内置 Sink接口
Stream 消息生产者
<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>study-springcloudartifactId>
<groupId>com.fsgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>fs-stream-RabbitMQ-provider-8801artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-stream-rabbitartifactId>
dependency>
dependencies>
project>
server:
port: 8801
spring:
application:
name: fs-stream-provider
cloud:
stream:
# 定义绑定,绑定到哪个消息中间件上
binders: #在此处声明配置要绑定的RabbitMQ的服务信息
fs_Rabbit: # 表示定义的名称,用binding整合,随便自定义
type: rabbit # 消息组件类型
environment: #设置RabbitMQ的相关配置
spring:
rabbitmq:
host: 192.168.93.132
port: 5672
username: root
password: root
virtual-host: /
bindings: #服务的整合处理
output: # 这个名字是一个管道的名称,使用默认的output
default-binder: fs_Rabbit # 设置要绑定的消息服务的具体设置, 若idea爆红没关系
destination: fs_Exchange #表示要使用的Exchange交换机名称 自定义 消息发送的目的地
content-type: application/json # 设置消息类型,本次为json 文本设置为test/plain
#eureka:
# client:
# service-url:
# defaultZone: http://fseureka7001.com:7001/eureka,http://fseureka7002.com:7002/eureka,http://fseureka7003.com:7003/eureka
# instance:
# lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认30秒)
# lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒间隔(默认是90秒)
# instance-id: send-8801.com # 在消息列表显示主机名称
# prefer-ip-address: true # 访问的路径变ip地址
package com.fs.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class StreamMain8801 {
public static void main(String[] args) {
SpringApplication.run(StreamMain8801.class,args);
}
}
package com.fs.springcloud.service;
public interface IMessageProvider {
public String send();
}
package com.fs.springcloud.service.impl;
import com.fs.springcloud.service.IMessageProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import java.util.UUID;
//定义消息的推送管道
@Service
@EnableBinding(Source.class)//指信道channel和Exchange绑定在一起
public class IMessageProviderImpl implements IMessageProvider {
@Autowired
private MessageChannel output;//消息发送管道
//重写send方法,发送消息
@Override
public String send() {
String s = UUID.randomUUID().toString()+"我是provider使用StreamRabbitMQ发送的消息~~~";
output.send(MessageBuilder.withPayload(s).build());
System.out.println("~~~~消息"+s);
return "success";
}
}
package com.fs.springcloud.controller;
import com.fs.springcloud.service.IMessageProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/*
提供方法,发送消息
*/
@RestController
public class SendMessageController {
@Autowired
private IMessageProvider iMessageProvider;
@RequestMapping("/sendMessage")
public String sendMessage(){
return iMessageProvider.send();
}
}
<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>study-springcloudartifactId>
<groupId>com.fsgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>fs-stream-RabbitMQ-consumer-9901artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-stream-rabbitartifactId>
dependency>
dependencies>
project>
server:
port: 9901
spring:
application:
name: fs-stream-consumer
cloud:
stream:
binders: #在此处声明配置要绑定的RabbitMQ的服务信息
fs_Rabbit: # 表示定义的名称,用binding整合
type: rabbit # 消息组件类型
environment: #设置RabbitMQ的相关配置
spring:
rabbitmq:
host: 192.168.93.132
port: 5672
username: root #RabbitMQ的账户密码
password: root
virtual-host: /
bindings: #服务的整合处理
input: # 这个名字是一个通道的名称 默认input
default-binder: fs_Rabbit # 设置要绑定的消息服务的具体设置, 爆红没关系
destination: fs_Exchange #表示要使用的Exchange名称定义
content-type: application/json # 设置消息类型,本次为json 文本设置为test/plain
group: xiaofuA #对消费者进行分组,将2个微服务分成同一个组,轮询消费,解决重复消费
#eureka:
# client:
# service-url:
# defaultZone: http://fseureka7001.com:7001/eureka,http://fseureka7002.com:7002/eureka,http://fseureka7003.com:7003/eureka
# instance:
# lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认30秒)
# lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒间隔(默认是90秒)
# instance-id: receive-8803.com # 在消息列表显示主机名称
# prefer-ip-address: true # 访问的路径变ip地址
package com.fs.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/*
故障现象,重复消费
微服务应用放置于同一个group中,就能够保证消息只会被其中一个应用消费一次
不同的组是可以重复消费的,同一个租内会发生竞争关系,只有其中一个可以消费
*/
@SpringBootApplication
public class StreamRabbitMQMain9901 {
public static void main(String[] args) {
SpringApplication.run(StreamRabbitMQMain9901.class,args);
}
}
package com.fs.springcloud.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
/*
消息接收类
*/
@Component
@EnableBinding(Sink.class)//绑定消息
public class ReceiveMessageListenerController {
@Value("${server.port}")
private String serverPort;
//定义消息接收方法
@StreamListener(Sink.INPUT)
public void input(Message<String> message){
//打印消息数据
//只要提供方发生了消息,这里就会被执行
System.out.println("消费者,~~~~~收到的消息:"+message.getPayload()+",port:"+serverPort);
}
}
首先打开RabbitMQ
启动2个服务:
fs-stream-RabbitMQ-provider-8801
fs-stream-RabbitMQ-consumer-9901
浏览器发送服务提供方法的controller的地址调用send方法,发送消息到RabbitMQ中
然后观看控9901的控制台
• Spring Cloud Sleuth 其实是一个工具,它在整个分布式系统中能跟踪一个用户请求的过程,捕获这些跟踪数据,就能构建微服务的整个调用链的视图,这是调试和监控微服务的关键工具。
• 耗时分析
• 可视化错误
• 链路优化
• Zipkin 是 Twitter 的一个开源项目,它致力于收集服务的定时数据,以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。
定义:
使用:
服务端(ZipKin)
jar包运行
docker 运行
客户端
导包
>
>org.springframework.cloud >
>spring-cloud-starter-zipkin >
>
配置
spring:
zipkin:
base-url: http://localhost:9411/ # 设置zipkin的服务端路径
sleuth:
sampler:
probability: 1 # 采集率 默认 0.1 百分之十。
编码
无需任何编码,服务自动被采集数据到zipkin