spring cloud stream 基础使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mr_zhuqiang/article/details/84820076


依赖

 compile 'org.springframework.cloud:spring-cloud-starter-stream-rabbit'

本章记录下调研 spring cloud stream 基础用法的结果;

基础

yml 配置

spring:
  rabbitmq:
    host: 192.168.7.106
    port: 5672
    username: xxx
    password: 123456

消费端

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;

/**
 * <pre>
 * 使用默认的队列名,消费端
 * </pre>
 * @author zhuqiang
 * @date 2018/12/4 13:40
 */
@EnableBinding(value = {Sink.class})
@Slf4j
public class SinkReceiver {
    @StreamListener(Sink.INPUT)
    public void receive(Object payload) {
        log.info("Received from default channel : {}", payload.toString());
    }
}

生产端,使用测试来发送

@RunWith(SpringRunner.class)
@EnableBinding(value = {ReceiverAppTest.SinkSender.class})
public class ReceiverAppTest {
    @Autowired
    private SinkSender sinkSender;

    @Test
    public void sinkSenderTester() {
        sinkSender.output().send(MessageBuilder.withPayload("produce a message to " + Sink.INPUT + " channel").build());
    }

    public interface SinkSender {
        @Output(Sink.INPUT)
        MessageChannel output();
    }
}

分组、自定义、重试、处理错误、死信队列

  • 分组 : 分组的作用是,多个相同的分布式微服务启动的话,让他们在一个队列组里面,这样每次就只能有一个实例被消费了
  • 自定义:基础里面是使用框架预定义的队列名称,这里可以自定义
  • 重试:在处理消息的时候,如果抛出了异常,则会再次委派给你处理
  • 处理错误:在处理消息的时候,如果消息抛出了异常,你希望处理这个错误的话
  • 死信队列:当这个消息处理失败多次的时候,那么很有可能是一个不可处理的消息,放入死信队列

自定义、默认重试机制与错误处理

import org.springframework.cloud.stream.annotation.Input;
import org.springframework.messaging.SubscribableChannel;

/**
 * <pre>
 *  定义消费端,信息接收处理
 * </pre>
 * @author zhuqiang
 * @date 2018/12/3 15:31
 */
public interface CmdInput {
    String INPUT = “xxxxx”;

    @Input(INPUT)
    SubscribableChannel input();
}
@Component
@EnableBinding(CmdInput .class) // 开启绑定接口
@Slf4j
public class NoticeCmdReceiver {

    // 默认抛出异常的话,默认重试 3 次
    // 如果有自定义的错误处理则不会重试
    @StreamListener(target = NoticeCmdInput.INPUT)
    public void process(NoticeCmdRequest cmd) {
        log.info("StreamListener process message {}", cmd);
        throw new RuntimeException("xxx");
    }
    // 处理错误通道名称格式是:通道名.组名.errors
    // 不会通过 队列传递,应该是内部调用
    @ServiceActivator(inputChannel = CmdInput.INPUT + ".group.errors")
    public void processErrorerror(Message<?> message) {
        System.out.println("Handling ERROR: " + message);
    }
}    

注意:yml 中没有额外的配置;

死信队列与分组

yml 配置

spring:
  cloud:
    stream:
      bindings:
        # 多个实例消费的时候可以唯一消费
        xxxxx:
          destination: xxxxx
          group: group # 使用死信队列必须分组
          consumer:
            max_attempt: 3  # 最大重试次数,默认是 3 次
            dlq-ttl: 2000  # 重试间隔时间
            republishToDlq: true
            #  deadLetterQueueName: 手动写死死信队列名称,也可以像下面这样开启自动名称,如这里自动生成 xxxxx.group.dlq
      rabbit:
        bindings:
          xxxxx:
            # 死信队列
            consumer:
              auto-bind-dlq: true

增加该配置之后,就会回 xxxxx 的队列再自动生成一个死信队列 xxxxx.group.dlq;
这里的配置加上最上面的代码效果就是:

  1. 失败会重试 3 次
  2. 3 次失败就会进入错误处理方法。而不会进入死信队列;死信队列与错误处理是互斥的;

总结

  1. 分组:单实例消费
  2. 重试:没有配置 consumer.max_attempt 的话,默认是 3 次,且有错误处理的话,不会重试
  3. 处理错误:处理错误与死信队列是互斥的,要么被处理了,要么发往死信队列

猜你喜欢

转载自blog.csdn.net/mr_zhuqiang/article/details/84820076
今日推荐