今天是2020-12-13
一。spring cloud stream 消息驱动
1.目前仅支持rabbitmq与kafka
2. 作用:屏蔽底层消息中间件的差异,降低了以往不同消息中间件传递消息时切换的成本,降低了系统耦合。
3. 通过定义绑定器binder作为中间层,实现了应用程序与消息中间件细节的隔离。
4. 消息的通信方式遵循了rabbitmq的topic交换机和kafka的topic,即发布-订阅模式
5. 常用组件:绑定器binder、通道channel
6. spring cloud bus进一步封装了spring cloud stream。stream一般是需要异步通知时使用,而bus一般是和config配合使用来达到热更新配置文件。一般情况下用stream就行,但bus也能做的更好
二。绑定器binder
binder中的input对应消费者,output对应生产者。
三。通道channel
是队列queue的抽象,通过channel即可对队列进行配置
四。source和sink
source就是生产者端的stream,sink就是消费者端的stream
五。常用注解。
1.@input,标注应用程序从中间件接受消息的通道
2.@output,标注应用程序给中间件发送消息的通道
3.@streamlistener,监听队列,用于消费者队列的消息接受
4.@enablebinding,将channel和exchange绑定
六。stream使用
生产者端:
1.pom:spring-cloud-starter-stream-rabbit
2.application.yml:
server:
port: 8801
spring:
application:
name: cloud-stream-provider
cloud:
stream:
#在此配置要绑定的rabbitmq信息
binders:
#表示定义的名称
defaultrabbit:
#消息中间件的类型
type: rabbit
#rabbitmq的相关环境配置
environment:
spring:
rabbitmq:
host: #你rabbimq所在的服务器的ip
port: 5672
username: guest
password: guest
#服务的整合处理
bindings:
#通道的名称,表示我们是生产者
output:
#要使用的交换机的名称定义
destination: studyExchange
#设置本次消息类型
content-type: application/json
default-binder: defaultRabbit
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
instance:
prefer-ip-address: true
3.创建接口:
public interface IMessageProvider {
public String send();
}
4.接口实现类:
@EnableBinding(Source.class) //定义消息的推送管道
@Slf4j
public class IMessageProviderImpl implements IMessageProvider {
//消息发送的管道
@Autowired
private MessageChannel output;
@Override
public String send() {
String serial= UUID.randomUUID().toString();
output.send(MessageBuilder.withPayload(serial).build());
log.info(serial);
return null;
}
}
5.控制器:
@RestController
public class SendMessageController {
@Autowired
private IMessageProvider iMessageProvider;
@GetMapping("/send")
public String sendMessage(){
return iMessageProvider.send();
}
}
6.启动各模块,访问rabbitmq,可以看到多出了一个交换机:studyExchange,成功
消费者端:
1.pom与消费者一致
2.applicaition.yml,修改端口号,将output改为input,表示我们是消费者
3.创建接受类:
@Component
@EnableBinding(Sink.class)
public class ReceiveMessageController {
@Value("${server.port}")
private String serverport;
@StreamListener(Sink.INPUT)
public void input(Message<String> message){
System.out.println("consumer receive:"+message.getPayload()+"\t"+serverport);
}
}
4.模块启动后可以看到studyExchange交换机绑定了一个队列,就是我们的消费者
5.访问生产者 发送消息的方法,可以看到消费者程序后台自动打印接受的消息,即订阅模式
七。消息的重复消费与持久化
新建一个相同的消费者微服务后,生产者发送消息,两个消费者都会接收到,因为每个微服务默认的组名不同,但是我们的预期是这两个微服务同组竞争消费,使用stream的分组来解决这个问题:同组内竞争消费–轮询,不同组可以重复消费–广播。
实现自定义分组:
application.yml:
#服务的整合处理
bindings:
#通道的名称,表示我们是生产者
input:
#要使用的交换机的名称定义
destination: studyExchange
#设置本次消息类型
content-type: application/json
default-binder: defaultRabbit
#队列的组名
group: group2
如上定义即可,想实现服务同组就定义同一个组名,而且可以看到,同组的时候stream使用轮询选择给组内某个微服务消费消息。
group属性的另一个作用:如果微服务配置了group属性,也就是自定义了组名,那么即使服务关闭,所在组也不会被删除,重启后可以消费关闭期间队列接收到的消息;如果微服务没有自定义group,那么启动后会被分配随机组名,服务关闭后随机组名就会被删除,重启后无法消费关闭期间的消息。
八。spring cloud Sleuth 分布式请求链路跟踪
在微服务应用中,一个客户端发送的请求在后端服务中都可能经过多个不同的服务调用来协同返回最终结果,当应用越来越庞大时,每次请求产生的服务调用链路就可能越来越长,中间某个环节的失败就可能有严重后果,所以需要对请求链路的监控。
zipkin可视化界面安装与访问:
1.docker pull openzipkin/zipkin
2.docker run -d -p 4321:4321 -p 9411:9411 --name zipkin openzipkin/zipkin
3.访问你的zipkin所在ip:9411/zipkin,阿里云服务器记得开放安全组端口9411
一条请求链路常用的概念:
1.traceid,唯一标识一条请求链路
2.spanid,标识对链路上的某个服务发起的请求信息,spanid通过parentid关联
3.parentid,请求发起者的服务的spanid,也就是这条调用链路上前一个服务的spanid
简易流程:
1.traceid:null,spanid:null,请求服务1
2.traceid:x,spanid:a,服务一接受请求,链路开始
3.spanid:b,parentid:a,服务一请求服务二
4.spanid:c,parentid:b,服务二请求服务三
…
九。slueth使用
以80消费者和8001提供者为例:
8001提供者:
1.pom:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
2.application,yml:
zipkin:
base-url: #你的zipkin所在服务器的ip
sleuth:
sampler:
#采样值在0-1之间,1表示全部采集
probability: 1
3.controller:
@GetMapping("/payment/zipkin")
public String paymentZipkin(){
return "hello! this is zipkin test!";
}
80消费者:
1.pom和yml与提供者一致
2.feign接口:
@RequestMapping("/payment/zipkin")
public String paymentZipkin();
3.controller:
@GetMapping("/consumer/zipkin")
public String paymentZipkin(){
return paymentFeignService.paymentZipkin();
}
配置完成后启动各个模块,访问localhost/consumer/zipkin,然后访问zipkin可视化界面,查询条件选择服务名:cloud-order-service,spanname选择get consumer/zipkin,点击查询即可看到刚刚的请求链路信息。
九。感言
到这里,spring cloud算是告一段落了,可能今天可能明天又得开始spring cloud alibaba的学习,希望自己能持续的学习下去。也不希望自己只是死学,在spring cloud告一段落的情况下,是时候花一点时间做一下自己的知识树的梳理了,好好规划一下接下来的学习计划,当然…cloud alibaba肯定必学…因为nacos太牛了0 0