Spring Cloud第八站Stream

Stream简介

  Stream又名消息驱动,为什么要引入Stream?
  在微服务架构中,我们可能会因为业务的原因,而要使用到多种消息队列的场景。但是,对于开发者而言。每多学习一门新的技术,就要花费一定的时间与经历。而Stream的引入,就是为了方便开发人员,可以不用在关注不同的MQ之间的方言细节,可以将更多的经历花费在业务逻辑的编写上。(类似于Hibernate)
  用一句话来概括Stream–屏蔽底层消息中间件的差异,降低切换成本,统一消息的编程模型。
  虽然Stream的设计理念是为了统一消息的编码模型。但是到目前为止,Stream只支持RabbitMQ、Kafka。

Stream常用注解

  • @Input 注解标识输入通道,通过该输入通道接受到消息进入程序(对应消费者)
  • @Output 注解标识输入通道,发布的消息将通过该通道离开程序(对应生产者)
  • @StreamListener 监听队列,用于消费者的队列的消息接受
  • @EnableBinding 指通道channel与exchange绑定在一起

Stream对应的模型
Spring Cloud第八站Stream_第1张图片
对应的生产者与消费者模型
Spring Cloud第八站Stream_第2张图片

Stream生产者构建

  1. 新建生产者模块cloud-stream-provider8801,导入stream相关依赖
		<!-- 当前使用的是rabbitmq消息中间件,如果使用的Kafka请导入Kafka相关依赖 -->
		<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: #配置要绑定的rabbitmq相关的信息
        defaultRabbit:
          type: rabbit #消息中间件rabbit或Kafka
          environment:
            spring:
              rabbitmq:
                host: localhost
                port: 5672
                username: guest
                password: guest
      bindings: #服务整合处理
        output:
          destination: studyExchange #使用的exchange的名称
          content-type: application/json  #设置发送的消息类型,此处为json格式
          	binder:  defaultRabbit #设置要绑定的消息服务的具体设置
  1. 编写发送消息的service(核心service上配置绑定的消息通道)
@Service
@EnableBinding(Source.class) //定义消息的推送管道
@Slf4j
public class ProviderServiceImpl implements ProviderService {
     

    @Autowired
    private MessageChannel output;

    @Override
    public String send() {
     
        String serial = UUID.randomUUID().toString();
        output.send(MessageBuilder.withPayload(serial).build());
        log.info(serial);
        return null;
    }
}
  1. 编写访问的接口
@RestController
public class ProviderController {
     

    @Autowired
    private ProviderService providerService;

    @GetMapping(path = "/send")
    public String sendProvider() {
     
        return providerService.send();
    }
}
  1. 测试
    访问send接口,观察rabbitmq控制台。发现控制台有消息发送则证明配置成功
    Spring Cloud第八站Stream_第3张图片

Stream消费者构建

单消费者构建

  1. 新建消费者模块cloud-stream-consumer8802,导入依赖(与生产者相同)
		<!-- 当前使用的是rabbitmq消息中间件,如果使用的Kafka请导入Kafka相关依赖 -->
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
  1. 配置yml依赖
```java
spring:
  application:
    name: cloud-stream-provider
  cloud:
    stream:
      binders: #配置要绑定的rabbitmq相关的信息
        defaultRabbit:
          type: rabbit #消息中间件rabbit或Kafka
          environment:
            spring:
              rabbitmq:
                host: localhost
                port: 5672
                username: guest
                password: guest
      bindings: #服务整合处理
        input:  #---------------------与生产不同点,将输出改为输入流
          destination: studyExchange #使用的exchange的名称
          content-type: application/json  #设置发送的消息类型,此处为json格式
          	binder:  defaultRabbit #设置要绑定的消息服务的具体设置

 3. 编写监听生产者的controller接口

```java
@Component
@EnableBinding(Sink.class)	//编写绑定类型
@Slf4j
public class MessageListenerController {

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

    @StreamListener(Sink.INPUT)	//监听程序的输入
    public void input(Message message) {	//此处message的泛型需要与生产者端传输的对象相同
        log.info(port + message.getPayload());
    }
}

重复消费问题与持久化问题
  但是,此种配置下。会出现多消费者端,重复消费问题。而Spring Cloud Stream默认的是按照组,来分配给消费者消息的。当消费者两两间是同一个组,则同组消费者轮询发布。不同组,则将同一消息重复发送给不同组成员。如果不进行配置的话Stream会默认给消费者模块,分配一个流水号。所以也就造成成创建组不同,会重复消费者问题。

解决办法,yml中引入分组配置

bindings: #服务整合处理
   input:
     group: groupA	#自定义分组命名

group配置在解决了重复消费的问题同时,还解决了持久化问题。即使消费者端宕机,重启后,消费者端仍能拿到消息。

你可能感兴趣的:(spring,cloud)