Stream
Stream的作用
Stream可以帮助我们不去关注使用的MQ种类,直接使用Stream的API和Binder交互,从而让Binder和指定的消息队列交互,如果消息队列修改了,不需要关注(暂时只支持kafka和RabbitMQ)
使用方式
生产者导入依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-stream-rabbit</artifactId> </dependency>
配置文件
spring: # 连接RabbitMQ rabbitmq: host: 192.168.199.109 port: 5672 username: test password: test virtual-host: /test
指定接口配置使用的队列
public interface StreamClient { @Output(value = "cloud-queue") MessageChannel output(); }
在启动类上,加载接口
@EnableBinding(StreamClient.class)
创建controller方法,发送消息到cloud-queue队列
@Autowired private StreamClient streamClient; @GetMapping("/sendMsg") public String sendMsg(){ >streamClient.output().send(MessageBuilder.withPayload("Hello Stream").build()); return "ok!!!"; }
启动RabbitMQ
消费者导入依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-stream-rabbit</artifactId> </dependency>
配置文件
spring: # 连接RabbitMQ rabbitmq: host: 192.168.199.109 port: 5672 username: test password: test virtual-host: /test
指定接口配置监听的队列
public interface StreamClient { @Input("cloud-queue") SubscribableChannel input(); }
在启动类添加注解,加载接口
@EnableBinding(StreamClient.class)
创建Listener监听队列中的消息
@Component @EnableBinding(StreamClient.class) public class CloudQueueListener { @StreamListener("cloud-queue") public void listen(Object msg){ System.out.println(msg); } }
避免重复消费
- Stream在消费者启动监听队列时,Stream会在你指定的队列名称的基础上再添加一个随机的后缀,作为队列的完整名称。
- 添加Stream的配置信息,指定消费者组,可以让多个消费者监听一个RabbitMQ的队列,保证一个消息只会被消费者组中的一个服务消费到。
spring: cloud: stream: bindings: cloud-queue: # 接口中指定队列的名称 group: search # 指定消费者组的名称
手动Ack
默认情况下,Stream是自动Ack机制
开启手动Ack
spring: cloud: stream: rabbit: bindings: cloud-queue: # 接口中配置的队列名称 consumer: acknowledgeMode: manual # 开启手动Ack
消费者代码端,指定channel提交ack
@StreamListener("cloud-queue") public void listen(Object msg, @Header(name = AmqpHeaders.CHANNEL) Channel channel, @Header(name = AmqpHeaders.DELIVERY_TAG) Long deliveryTag) { System.out.println(msg); channel.basicAck(deliveryTag,false); //ack }