SpringCloud-消息驱动(Stream)

 

Stream

概述

https://spring.io/projects/spring-cloud-stream#overview

https://docs.spring.io/spring-cloud-stream/docs/current/reference/html/

Stream解决什么问题?

当系统中使用多个不同的MQ时,使用spring cloud stream可以屏蔽 不同消息中间件的差异,统一消息的编程模型;

what

Spring Cloud Stream is a framework for building highly scalable event-driven microservices connected with shared messaging systems.

Spring Cloud Stream 是一个消息驱动的微服务框架;

应用程序 通过inputs/outputs 与 SpringCloudStream的binder进行交互;

通过配置进行binding,SpringCloudStream的binder负责与MQ交互;

目前仅支持 RabbitMQ、Kafka;

设计思想

标准MQ

 

生产者与消费者 通过Message 传递内容;

Message走特定的通道MessageChannel;

Message生产者生产Message,Message订阅者消费Message;

为什么要用SpringCloudStream?

假设系统同时使用RabbitMQ、Kafka,由于这2个MQ的架构不同(比如RabbitMQ有exchange、Kafka有Topic和Partitions);

 

不同MQ的差异导致实际项目开发造成了困扰,比如要将一种MQ的内容迁移至另一种MQ,无疑是一场灾难;

此时MQ与系统严重耦合,而SpringCloudStream提供了一种解耦的方式;

How

在没有Binder的情况下,Spring应用要与具体的MQ进行交互,不同的MQ有差异;

通过 定义Binder作为中间层,完美实现了 应用程序与MQ 的隔离

通过 向应用程序暴露统一的channel,使得应用程序不需要考虑不同MQ的差异

  (Input:消费者、Output:生产者)

 

SpringCloudStream标准流程 

 

 

 

Binder:  

  连接MQ,屏蔽不同MQ的差异;

Channel:

  

Source/Sink:

  输出:从SpringCloudStream发出消息

  输入:接收消息

编码API及常用注解 

 

How

消息生产者

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


spring:
  application:
    name: stream-rabbit-provider

  cloud:
    stream:
      binders:  #要绑定的RabbitMQ的服务信息
        defaultRabbit:  #定义的名称,用于binding整合
          type: rabbit  #MQ类型
          environment:  #RabbitMQ的相关环境配置
            spring:
              rabbit:
                host: localhost
                port: 5672
                username: guest
                password: guest

      bindings: #服务的整合处理
        output: #消息生产者
          destination: studyExchange  #Rabbit的Exchange名称
          content-type: application/json  #消息类型
          binder: defaultRabbit


@EnableBinding(value = Source.class)
public class MessageSender {

    @Autowired
    private MessageChannel output;

    public String send(){
        output.send(MessageBuilder.withPayload("hhh").build());
        return UUID.randomUUID().toString();
    }

}


@RestController
public class MessageController {

    @Autowired
    private MessageSender messageSender;

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

}


@SpringBootApplication
public class StreamRabbitProvider8801 {

    public static void main(String[] args) {
        SpringApplication.run(StreamRabbitProvider8801.class, args);
    }

}

http://localhost:8801/sendMsg

  

消息消费者

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


spring:
  application:
    name: stream-rabbit-consumer

  cloud:
    stream:
      binders:  #要绑定的RabbitMQ的服务信息
        defaultRabbit:  #定义的名称,用于binding整合
          type: rabbit  #MQ类型
          environment:  #RabbitMQ的相关环境配置
            spring:
              rabbit:
                host: localhost
                port: 5672
                username: guest
                password: guest

      bindings: #服务的整合处理
        input: #消息消费者
          destination: studyExchange  #Rabbit的Exchange名称
          content-type: application/json  #消息类型
          binder: defaultRabbit


@Component
@EnableBinding(value = Sink.class)
public class MessageConsumer {

    @StreamListener(value = Sink.INPUT)
    public void consume(Message<String> message){
        System.out.println("msg: "+ message.getPayload());
    }

}


@SpringBootApplication
public class StreamRabbitConsumer8802 {

    public static void main(String[] args) {
        SpringApplication.run(StreamRabbitConsumer8802.class, args);
    }

}

  

分组消费/持久化 

前言

当微服务是集群部署时,相同业务功能的微服务都会消费消息,存在重复消费的问题;

重复消费解决

使用SpringCloudStream的group;

  (Stream中处于同一个group中的多个消费者是竞争关系,这样能保证消息只会被其中一个服务消费)

 

 

如果不显式多消费者进行分组,默认一个消费者一个组;

分组

原理

  相同业务功能的微服务可以分为一个group,这样同一个group内多个微服务是竞争关系,保证仅有一个消费者可以消费;

spring:
  application:
    name: stream-rabbit-consumer

  cloud:
    stream:
      binders:  #要绑定的RabbitMQ的服务信息
        defaultRabbit:  #定义的名称,用于binding整合
          type: rabbit  #MQ类型
          environment:  #RabbitMQ的相关环境配置
            spring:
              rabbit:
                host: localhost
                port: 5672
                username: guest
                password: guest

      bindings: #服务的整合处理
        input: #消息消费者
          destination: studyExchange  #Rabbit的Exchange名称
          content-type: application/json  #消息类型
          binder: defaultRabbit
          group: testGroup        #消费者group

  

持久化

对微服务 显式指定group,应用重启后 会自动获取未消费的消息;

如果不显式指定group,由于微服务故障,将会导致消息丢失;

 

posted on 2022-08-12 16:22  anpeiyong  阅读(216)  评论(0编辑  收藏  举报

导航