SpringCloud H版系列11--Stream为微服务应用构建消息驱动能力


书接上文,继续跟着周阳老师学习SpringCloud的消息驱动框架Stream。

一、Spring Cloud Stream

1.1 Stream

是一个用来为微服务应用构建消息驱动能力的框架。它可以基于 Spring Boot 来创建独立的、可用于生产的 Spring 应用程序。Spring Cloud Stream 为一些供应商的消息中间件产品提供了个性化的自动化配置实现,并引入了发布-订阅、消费组、分区这三个核心概念。通过使用 Spring Cloud Stream,可以有效简化开发人员对消息中间件的使用复杂度,让系统开发人员可以有更多的精力关注于核心业务逻辑的处理。但是目前 Spring Cloud Stream 只支持 RabbitMQ 和 Kafka 的自动化配置。

一句话:屏蔽底层消息中间件的差异,降低切换成本,统一消息的编程模型。

1.2 Stream处理架构

通过定义绑定器Binder作为中间层,实现了应用程序与消息中间件之间的隔离

1.3 Stream标准流程套路

在这里插入图片描述
Binder:很方便的连接中间件,屏蔽差异。
channel:通道,是队列Queue的一种抽象,在消息通讯系统中就是实现存储和转发的媒介,通过channel对队列进行配置。
source和sink:简单理解为消息的输入输出。

1.4 编码API和注解

在这里插入图片描述

二、实战

2.1 新建子模块8801,作为消息驱动的生产者

cloud-stream-rabbitmq-provider8801 消息生产模块
application.yml

server:
  port: 8801
spring:
  application:
    name: cloud-stream-provider
  cloud:
    stream:
      binders:  #需要绑定的rabbitmq的服务信息
        defaultRabbit: #定义的名称,用于binding整合
            type: rabbit #消息组件类型
            environment: #环境配置
              spring:
                rabbitmq:
                  host: localhost
                  port: 5672
                  username: guest
                  password: guest
      bindings: # 服务的整合处理
        output: # 名字是一个通道的名称,发送
          destination: studyExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为json
          binder: defaultRabbit #设置要绑定的消息服务的具体设置
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    #renewal表示eureka client向eureka server发送心跳的频率,如果在指定时间内未收到心跳,则移除实例
    lease-renewal-interval-in-seconds: 2  #设置心跳时间间隔,默认30秒
    #expiration表示eureka server获取上一个心跳之后,等待下一个心跳的秒数,默认90S
    #若不能在指定时间间隔内接收到实例,则移除此实例,并禁止此实例的流量
    lease-expiration-duration-in-seconds: 5  #设置接收时间间隔

    instance-id: send-8801.com # 主机名
    prefer-ip-address: true   # 显示ip

StreamMQMain8801主启动类

@SpringBootApplication
public class StreamMQMain8801 {
    //1.先启动7001  2.再启动8801,连续多次访问http://localhost:8801/sendMessageTest
    //查看http://localhost:15672下的Exchanges绑定的交换机信息
    public static void main(String[] args) {
        SpringApplication.run(StreamMQMain8801.class,args);
    }
}

IMessageProvider接口

public interface IMessageProvider {
    String send();//消息发送接口
}

MessageProviderImpl

@EnableBinding(Source.class)//定义消息的推送广告,此注解指信道channel和exchange绑定在一起
public class MessageProviderImpl implements IMessageProvider {
    @Resource
    private MessageChannel output; //消息发送管道

    @Override
    public String send() {
        String serial = UUID.randomUUID().toString();
        output.send(MessageBuilder.withPayload(serial).build());
        System.out.println("*****serial: " +serial);
        return null;
    }
}

SendMessageController控制层

@RestController
public class SendMessageInfoController {
    @Resource
    private IMessageProvider messageProvider;

    @GetMapping("/sendMessageTest")
    public String sendMessageTest(){
        return messageProvider.send();
    }

}

8801 消息生产模块项目结构
在这里插入图片描述
8801测试步骤及结果
先启动7001 2.再启动8801,连续多次访问http://localhost:8801/sendMessageTest
再查看http://localhost:15672下的Exchanges绑定的交换机信息
在这里插入图片描述
在这里插入图片描述

2.2 新建子模块8802,作为消息驱动的消费者

cloud-stream-rabbitmq-consumer8802 消息消费模块
application.yml

server:
  port: 8802
spring:
  application:
    name: cloud-stream-consumer
  cloud:
    stream:
      binders:  #需要绑定的rabbitmq的服务信息
        defaultRabbit: #定义的名称,用于binding整合
            type: rabbit #消息组件类型
            environment: #环境配置
              spring:
                rabbitmq:
                  host: localhost
                  port: 5672
                  username: guest
                  password: guest
      bindings: # 服务的整合处理
        input: # 名字是一个通道的名称,消费
          destination: studyExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为json
          binder: defaultRabbit #设置要绑定的消息服务的具体设置
          group: atguiguA
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    lease-renewal-interval-in-seconds: 2
    lease-expiration-duration-in-seconds: 5
    instance-id: receive-8802.com
    prefer-ip-address: true

StreamMQMain8802

@SpringBootApplication
public class StreamMQMain8802 {
        //启动7001、8801、8802,测试8801发送,8802接收,
        //访问http://localhost:8801/sendMessageTest    
    public static void main(String[] args) {
          SpringApplication.run(StreamMQMain8802.class, args);
    }
}

ReceiveMessageListenerController

@Component
@Slf4j
@EnableBinding(Sink.class)   //指信道chanel和exchange绑定一起
public class ReceiveMessageListenerController {

    @Value("${server.port}")
    private String serverPort;

    @StreamListener(Sink.INPUT)  //监听队列,用于消费者的队列消息接收
    public void input(Message<String> message) {
        System.out.println("消费者1号,------>接收到的消息:"+message.getPayload()+"\t port" +serverPort);
    }

}

访问http://localhost:8801/sendMessageTest
只访问一次的测试结果
在这里插入图片描述
多次频繁访问测试结果
在这里插入图片描述
8802控制台输出结果
在这里插入图片描述
8801控制台输出结果
在这里插入图片描述

2.3 新建子模块8803,作为消息驱动的消费者(clone8802项目)

代码一致,主要区别是application.yml中端口号改为8803

2.3.1 消息重复消费问题

不同的组存在重复消费,相同的组之间竞争消费,只有一个被消费。
application.yml中不增加group组名,测试结果
连续访问http://localhost:8801/sendMessageTest两次
重复消费结果如下请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
application.yml中增加group组名
在这里插入图片描述
在这里插入图片描述
测试结果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.3.1 消息持久化

利用group分组实现消息持久化,演示步骤如下
1、停止8802和8803,将8802的group:atguiguA注释
2、8801线发送4条消息到RabbitMQ
3、先启动8802,无分组属性配置,后台没有打印出来消息
4、再启动8803,有分组属性配置,后台打印出MQ上消息
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
项目总体结构
在这里插入图片描述

源码下载地址

spring-cloud-01

参考文章
https://blog.csdn.net/qq_42107430/article/details/104788858
https://www.cnblogs.com/wwjj4811/p/13628099.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值