SpringCloud10-Stream

SpringCloud10-Stream

1.Stream

  1. 常见的消息中间件有ActiveMQ、RabbitMQ、RocketMQ、Kafka,多种消息中间件增加了维护成本,而Stream屏蔽底层消息中间件的差异,降低降低切换成本;同时提供统一消息的编程模型,自动的给我们在各种MQ内切换。

  2. Stream官网。https://docs.spring.io/spring-cloud-stream/docs/3.1.4/reference/html/

  3. Stream目前仅支持RabbitMQ、 Kafka之间的切换。

2.Stream核心概念

  1. Binder,很方便的连接中间件,屏蔽差异。
  2. Channel,通道,是队列Queue的一种抽象,在消息通讯系统中就是实现存储和转发的媒介,通过Channel对队列进行配置。
  3. Source和Sink,以Spring Cloud Stream自身为参照对象,从Stream发布消息就是输出,接受消息就是输入。

3.Stream工作流程

  1. 应用程序通过inputs或者outputs来与Stream中Binder对象交互。
  2. Stream的Binder对象负责与消息中间件交互。
  3. 工作流程图。

image

4.创建消息生产者微服务cloud-stream-rabbitmq-provider8801

  1. pom.xml
<!-- stream-rabbitMQ -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
  1. yml
spring:
  application:
    name: cloud-stream-provider
  cloud:
    stream:
      binders:
        defaultRabbit: # 表示定义的名称,用于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
                host: 127.0.0.1
                port: 5672
                username: guest
                password: guest
      bindings:
        output: # 这个名字是一个通道的名称
          destination: studyExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,json,文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置
  1. Main
@EnableEurekaClient
@SpringBootApplication
public class CloudStreamRabbitMQProvider8001Main {

    public static void main(String[] args) {
        SpringApplication.run(CloudStreamRabbitMQProvider8001Main.class, args);
    }
}
  1. controller省略
  2. service
public interface IMessageProvider {

    String send();
}

@Slf4j
@EnableBinding(value = {
        Source.class
}) //3.1过时,可以使用 Input和Output
public class MessageProviderImpl implements IMessageProvider {

    /**
     * Stream核心
     *  Source或者Sink
     *  Channel。output,消息的提供者,生产者,相对于当前应用将消息输出到 RabbitMQ中
     *  Binding
     */
    @Resource
    private MessageChannel output;

    @Override
    public String send() {
        UUID randomUUID = UUID.randomUUID();
        output.send(MessageBuilder.withPayload(randomUUID).build());
        log.info("message : {}", randomUUID);
        return randomUUID.toString();
    }
}
  1. 服务启动后会在,RabbitMQ中创建一个studyExchage的topic。

7.创建消息消费者cloud-stream-rabbitmq-consumer8802

  1. pom.xml、yml、Main不变。
  2. controller
@Slf4j
@RestController
@EnableBinding(Sink.class)
public class MessageController {

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

    // 监听
    @StreamListener(Sink.INPUT)
    public void receive(Message<String> message) {
        log.info("message {}", message.getPayload() + "=====" + port);
    }
}
  1. 创建消息消费者cloud-stream-rabbitmq-consumer8803和8802保持一致。
  2. 使用8801生产消息,8802和8803同时消费消息。

8.重复消费消息的问题

  1. 不同的组是可以重复消费的,同一个组内会发生竞争关系,只有其中一个可以消费。
  2. stream在创建8802和8803时,默认情况下,没有指定分组,RabbitMQ会使用流水号作为组名。如 studyExchange.anonymous.CCrLMvYjQbmhtI7xrl0rnw。所以两个消费者会被放入不同的组中,产生重复消费的问题。
  3. 解决方法。将8802和8803放在相同的组中。同一个组内会发生竞争关系,只有其中一个可以消费。
  4. 为消息的消费者添加分组。
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 # 设置要绑定的消息服务的具体设置
          # 8802和8803同时放在cloud.stream.rabbitmq.a组中,将不会产生消息重复消费的问题。
          group: cloud.stream.rabbitmq.a

9.消息的持久化

  1. 当消费的消费者停机后再启动,是不会接受到停机这段时间RabbitMQ的消息,会造成消除丢失。可以使用分组类解决。
  2. 配置了group分组,停机后启动,可以接受到停机这段时间的消息的。但是如果8802和8803都停机了,8802和8803都配置了分组,且在同一个组中,8802消费完了消费停机时的消息,8803在启动时不会重复消费的。
posted @ 2021-10-07 20:02  行稳致远方  阅读(181)  评论(0)    收藏  举报