SpringCloud Stream消息驱动学习笔记

1、概述

1.1、是什么

官方定义 Spring Cloud Stream 是一个构建消息驱动微服务的框架。
应用程序通过 inputs 或者 outputs 来与 Spring Cloud Stream中binder对象交互。
通过我们配置来binding(绑定) ,而 Spring Cloud Stream 的 binder对象负责与消息中间件交互。所以,我们只需要搞清楚如何与 Spring Cloud Stream 交互就可以方便使用消息驱动的方式。

通过使用Spring Integration来连接消息代理中间件以实现消息事件驱动。
Spring Cloud Stream 为一些供应商的消息中间件产品提供了个性化的自动化配置实现,引用了发布-订阅、消费组、分区的三个核心概念。

目前仅支持RabbitMQ、Kafka。
Spring官网:https://spring.io/projects/spring-cloud-stream#overview
Stream中文手册:https://m.wang1314.com/doc/webapp/topic/20971999.html

1.2、设计思想

通过定义绑定器Binder作为中间层,实现了应用程序与消息中间件细节之间的隔离。处理架构
Binder可以生成Binding,Binding用来绑定消息容器的生产者和消费者,它有两种类型,INPUT和OUTPUT,INPUT对应于消费者,OUTPUT对应于生产者。
Stream中的消息通信方式遵循了发布-订阅模式,Topic主题进行广播,在RabbitMQ就是Exchange,在Kakfa中就是Topic。

1.3、标准流程套路

Binder:很方便的连接中间件,屏蔽差异。
Channel:通道,是队列Queue的一种抽象,在消息通讯系统中就是实现存储和转发的媒介,通过Channel对队列进行配置。
SourceSink:简单的可理解为参照对象是Spring Cloud Stream自身,
从Stream发布消息就是输出,接受消息就是输入。
常用API和注解在这里插入图片描述

2、构建

2.1、消息驱动的生产者

添加依赖

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

配置文件

spring:
  application:
    name: cloud-stream-provider
  cloud:
      stream:
        binders: # 在此处配置要绑定的rabbitmq的服务信息;
          defaultRabbit: # 表示定义的名称,用于于binding整合
            type: rabbit # 消息组件类型
            environment: # 设置rabbitmq的相关的环境配置
              spring:
                rabbitmq:
                  host: localhost
                  port: 5672
                  username: guest
                  password: guest
        bindings: # 服务的整合处理
          output: # 这个名字是一个通道的名称
            destination: studyExchange # 表示要使用的Exchange名称定义
            content-type: application/json # 设置消息类型,本次为json,文本则设置“text/plain”
            binder: defaultRabbit # 设置要绑定的消息服务的具体设置

主运行类

@SpringBootApplication
@EnableEurekaClient
public class StreamMQMain8801
{
    public static void main(String[] args)
    {
        SpringApplication.run(StreamMQMain8801.class,args);
    }
}

发送消息的接口

public interface IMessageProvider
{
    public String send() ;
}

实现类

@EnableBinding(Source.class)
public class IMessageProviderImpl implements IMessageProvider {

    @Resource
    private MessageChannel output;

    @Override
    public String sendMessage() {
        String serial = UUID.randomUUID().toString();
        boolean send = output.send(MessageBuilder.withPayload(serial).build());
        System.out.println("******serial******: " + serial);
        if (send) {
            return "发送成功:"+serial;
        } else {
            return "发送失败:"+serial;
        }
    }
}

Controller控制层

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

    @GetMapping(value = "/sendMessage")
    public String sendMessage()
    {
        return messageProvider.send();
    }
}

访问:http://localhost:8801/sendMessage可以发送消息,在RabbitMQ上面看见明显的消息波动峰

2.2、消息驱动的消费者

添加依赖

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

配置文件

spring:
  application:
    name: cloud-stream-consumer
  cloud:
      stream:
        binders: # 在此处配置要绑定的rabbitmq的服务信息;
          defaultRabbit: # 表示定义的名称,用于于binding整合
            type: rabbit # 消息组件类型
            environment: # 设置rabbitmq的相关的环境配置
              spring:
                rabbitmq:
                  host: localhost
                  port: 5672
                  username: guest
                  password: guest
        bindings: # 服务的整合处理
          input: # 这个名字是一个通道的名称
            destination: studyExchange # 表示要使用的Exchange名称定义
            content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
            binder: defaultRabbit # 设置要绑定的消息服务的具体设置

主运行类

@SpringBootApplication
@EnableEurekaClient
public class StreamMQMain8802
{
    public static void main(String[] args)
    {
        SpringApplication.run(StreamMQMain8802.class,args);
    }
}

Controller控制层

@Component
@EnableBinding(Sink.class)
public class ReceiveMessageListener {
    @Value("${server.port}")
    private String serverPort;

    @StreamListener(Sink.INPUT)
    public void input(Message<String> message) {
        System.out.println("所接收到的消息为======" + message.getPayload() + "\t    " + "端口号" + serverPort);
    }
}

使用:http://localhost:8801/sendMessage发送信息,在8802端口可以接收到消息,避免了中间件的不同,类似于一个Template可以进行发送和接收消息。

3、Stream的分组消费与持久化

3.1、分组消费

再次构建一个8803端口与8802类似,步骤省略
可以发现,如果生产者发送一条消息,两个消费者会同时消费一条消息,因为他们会自动生成一个流水号将他们划分到不同组,所以这里我们需要使用配置方法将其配置到同一个组去避免重复消费。
yml配置文件

spring:
  cloud:
    stream:
      bindings: 
        input: 
          group: 组名

这样就将其创建到同一个组去,再次发送消息,一条消息只会被一个消费端消费,不会重复消费

3.2、持久化

Stream默认开启持久化,即使消费端宕机了,之后生产者发送消息的时候服务端收不到,当消费端再次上线且组别没有发生变化的时候消费端还能消费到未消费的信息。这样自动实现了持久化。

4、学习地址

来源:哔哩哔哩尚硅谷:https://www.bilibili.com/video/BV18E411x7eT

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值