Stream

概述

1、Spring Cloud Stream 用于构建高度可扩展的事件驱动的微服务,并与共享消息系统相连

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

(1)构建、测试、部署以数据为中心的应用程序

(2)应用现代微服务架构模式,包括通过消息传递进行组合

(3)用以事件为中心的思维来解耦应用程序的责任。一个事件可以代表在时间上发生的事情,下游的消费者应用程序可以对其作出反应,而不知道它的来源或生产者的身份

(4)将业务逻辑移植到消息代理上(如:RabbitMQ、Apache Kafka、Amazon Kinesis)

(5)依靠框架的自动内容类型支持来处理常见的使用情况,扩展到不同的数据转换类型是可能的

 

设计思想

1、统一底层差异

(1)在没有绑定器这个概念的情况下,SpringBoot 应用要直接与消息中间件进行信息交互时,由于各消息中间件构建的初衷不同,它们的实现细节上会有较大的差异性

(2)通过定义绑定器作为中间层,完美地实现应用程序与消息中间件细节之间的隔离

(3)通过向应用程序暴露统一的 Channel,使得应用程序不需要再考虑各种不同的消息中间件实现

(4)Stream 对消息中间件的进一步封装,可以做到代码层面对中间件的无感知,甚至于动态的切换中间件,使得微服务开发的高度解耦,服务可以更多地关注自己的业务流程

2、Binder

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

(2)Binder 可以生成 Binding,Binding 用来绑定消息容器的生产者和消费者

(3)Binding 两种类型:INPUT 对应消费者,OUTPUT 对应生产者

3、Stream 消息通信方式遵循发布-订阅模式

(1)RabbitMQ:Exchange

(2)Kafka:Topic

 

Stream

1、结构

(1)Binder:连接中间件,屏蔽差异

(2)Channel:Queue 的抽象,存储、转发消息,通过 Channel 配置队列

(3)Source:输出、发布消息

(4)Sink:输入、接收消息

2、模型

(1)Middleware:消息中间件,只支持 RabbitMQ、Kafka

(2)Binder:应用与消息中间件之间的封装,连接中间件

3、注解

(1)@Input:输入通道,接收消息进入应用程序

(2)@Output:输出通道,发布消息离开应用程序

(3)@StreamListener:监听队列,用于消费者队列接收消息

(4)@EnableBinding:绑定 Channel、Exchange

 

消息驱动的生产者

1、核心依赖(以 RabbitMQ 为例)

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

2、yaml 配置

server:
  port: 8801

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

#省略注册配置

3、业务类

(1)发送消息接口

public interface MessageProvider {
    public String send() ;
}

(2)发送消息实现类

//理解为定义一个发送消息管道
@EnableBinding(Source.class)
public class MessageProviderImpl implements MessageProvider {

    //消息的发送管道
    @Resource
    private MessageChannel output;

    @Override
    public String send() {
        String serial = UUID.randomUUID().toString();
        //创建并发送消息
        //MessageBuilder
        this.output.send(MessageBuilder.withPayload(serial).build());
        return serial;
    }
}

(3)Controller

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

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

 

消息驱动的消费者

1、核心依赖(以 RabbitMQ 为例)

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

2、yaml 配置

server:
  port: 8802

spring:
  application:
    name: cloud-stream-consumer
  cloud:
    stream:
      # 配置绑定的RabbitMQ服务信息
      binders:
        # 表示定义的名称,用于binding整合
        defaultRabbit:
          # 消息组件类型
          type: rabbit
          # 设置RabbitMQ相关的环境配置
          environment:
            spring:
              rabbitmq:
                host: localhost
                port: 5672
                username: guest
                password: guest
      # 服务的整合处理
      bindings:
        # 通道的名称
        input:
          # 所使用的Exchange名称定义
          destination: TestExchange
          # 设置消息类型,文本则设置为 text/plain
          content-type: application/json
          # 设置要绑定的消息服务的具体设置
          binder: defaultRabbit

#省略注册配置

3、业务类

@Component
@EnableBinding(Sink.class)
public class ReceiveMessageListener {

    @StreamListener(Sink.INPUT)
    public void input(Message<String> message) {
        System.out.println(message.getPayload());
    }
}

 

消息分组

1、yaml 配置

spring:
  cloud:
    stream:
      # 服务的整合处理
      bindings:
        # 通道的名称
        input:
          group: ConsumerGroup1

2、解决:重复消费

(1)在 Stream 中,处于同一个 group 中的多个消费者是竞争关系,能够保证消息只会被其中一个应用消费一次

(2)不同组是可以全面消费(重复消费)

(3)同一组内会发生竞争关系,只有其中一个可以消费

3、解决:消息丢失

(1)无分组:应用重启后,不会获取停机时段的消息

(2)有分组:应用重启后,自动消费停机时段的消息,实现消息持久化

posted @   半条咸鱼  阅读(139)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示