版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mr_zhuqiang/article/details/84820076
spring cloud stream
依赖
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;
这里的配置加上最上面的代码效果就是:
- 失败会重试 3 次
- 3 次失败就会进入错误处理方法。而不会进入死信队列;死信队列与错误处理是互斥的;
总结
- 分组:单实例消费
- 重试:没有配置 consumer.max_attempt 的话,默认是 3 次,且有错误处理的话,不会重试
- 处理错误:处理错误与死信队列是互斥的,要么被处理了,要么发往死信队列