SpringCloud Stream是一个构建消息驱动微服务的框架,应用程序通过inputs或者 outputs来与SpringCloud Stream中的binder进行交互。其实就是为了适配底层消息队列的一个抽象出来的中间件。
使用 Stream 是为了 解决使用不同的消息队列技术所造成技术结构上的不同所带来的困扰。减少底层消息队列学习的一个成本,方便消息队列技术的迁移。
消息信道接口:
public interface MyTopic{ String INPUT = "delayed-consumer"; String OUTPUT = "delayed-producer"; // 消费者 @Input(INPUT) SubscribableChannel input(); // 生产者 @Output(OUTPUT) MessageChannel output(); }
生产者发送
@Autowired private MyTopic producer;
// 简单广播消息 @PostMapping("send") public void sendMessage(@RequestParam(value = "body") String body) { producer.output().send(MessageBuilder.withPayload(body).build()); }
消费者接受
@EnableBinding(value = { MyTopic.class }
// 自定义消息广播 @StreamListener(MyTopic.INPUT) public void consumeMyMessage(Object payload) { log.info("My message consumed successfully, payload={}", payload); }
配置文件
spring.application.name=stream-sample server.port=63003 # RabbitMQ连接字符串 spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest # 绑定Channel到broadcast spring.cloud.stream.bindings.myTopic-consumer.destination=broadcast spring.cloud.stream.bindings.myTopic-producer.destination=broadcast # 消息分组示例(消息分组后每个组都会收到发送的消息,每个组发一次消息,相当于广播) spring.cloud.stream.bindings.group-consumer.destination=group-topic spring.cloud.stream.bindings.group-producer.destination=group-topic spring.cloud.stream.bindings.group-consumer.group=Group-A ## 消息分区配置(分区相当于组内划分,一个组里的分区中只有一个分区能够收到消息,且可以指定某个特定分区来接受消息) ## 打开消费者的消费分区功能 spring.cloud.stream.bindings.group-consumer.consumer.partitioned=true ## 两个消息分区 spring.cloud.stream.bindings.group-producer.producer.partition-count=2 # SpEL (Key resolver) 可以定义复杂表达式生成Key # 我们这里用最简化的配置,只有索引参数为1的节点(消费者),才能消费消息 spring.cloud.stream.bindings.group-producer.producer.partition-key-expression=1 # 当前消费者实例总数 spring.cloud.stream.instanceCount=2 # 最大值instanceCount-1,当前实例的索引号 spring.cloud.stream.instanceIndex=1 # 延迟消息配置(需要在消息发送的时候设置消息header,添加“x-delay”,值为毫秒) spring.cloud.stream.bindings.delayed-consumer.destination=delayed-topic spring.cloud.stream.bindings.delayed-producer.destination=delayed-topic spring.cloud.stream.rabbit.bindings.delayed-producer.producer.delayed-exchange=true # 异常消息(单机版重试,相当于让本消费者再次尝试消费) spring.cloud.stream.bindings.error-consumer.destination=error-out-topic spring.cloud.stream.bindings.error-producer.destination=error-out-topic # 重试次数(本机重试) # 次数=1相当于不重试 spring.cloud.stream.bindings.error-consumer.consumer.max-attempts=2 # 异常消息(requeue重试,重新入队,相当于让生产者重新发送,可能是另外的消费者消费) spring.cloud.stream.bindings.requeue-consumer.destination=requeue-topic spring.cloud.stream.bindings.requeue-producer.destination=requeue-topic # 必须把max-attempts设置为1,否则requeue不能生效 spring.cloud.stream.bindings.requeue-consumer.consumer.max-attempts=1 spring.cloud.stream.bindings.requeue-consumer.group=requeue-group # 仅对当前requeue-consumer,开启requeue spring.cloud.stream.rabbit.bindings.requeue-consumer.consumer.requeueRejected=true # 默认全局开启requeue # spring.rabbitmq.listener.default-requeue-rejected=true # 死信队列配置(消费失败的消息集中转移到一个队列里,后续在处理,这个队列叫做死信队列) spring.cloud.stream.bindings.dlq-consumer.destination=dlq-topic spring.cloud.stream.bindings.dlq-producer.destination=dlq-topic spring.cloud.stream.bindings.dlq-consumer.consumer.max-attempts=2 spring.cloud.stream.bindings.dlq-consumer.group=dlq-group # 开启死信队列(默认 topic.dlq) spring.cloud.stream.rabbit.bindings.dlq-consumer.consumer.auto-bind-dlq=true # Fallback配置 spring.cloud.stream.bindings.fallback-consumer.destination=fallback-topic spring.cloud.stream.bindings.fallback-producer.destination=fallback-topic spring.cloud.stream.bindings.fallback-consumer.consumer.max-attempts=2 spring.cloud.stream.bindings.fallback-consumer.group=fallback-group # input channel -> fallback-topic.fallback-group.errors // 降级流程 @ServiceActivator(inputChannel = "fallback-topic.fallback-group.errors") public void fallback(Message<?> message) { log.info("fallback entered"); }