目前情况是,如果生产者一下子发送10条消息,在同一个group组的情况下,其中一个消费者可能消费了4条,另一个消费者可能收到 6条
但在某些场景下分组还不能满足我们的需求。比如,同时有多条同一个用户的数据发送过来,我们需要根据用户统计,但是消息被分散到了不同的集群节点上了,这时我们就可以考虑使用消息分区了。
当生产者将消息发送给多个消费者时,保证同一消息始终由同一个消费者实例接收和处理。消息分区是对消息分组的一种补充。
开始配置分区
生产者application.yml配置
server:
port: 8001 # 端口
spring:
application:
name: stream-producer # 应用名称
rabbitmq:
host: 127.0.0.1 # 服务器 IP
port: 5672 # 服务器端口
username: guest # 用户名
password: guest # 密码
virtual-host: / # 虚拟主机地址
cloud:
stream:
bindings:
# 消息发送通道
smsEmail_out:
destination: sourceMsg # 绑定的交换机名称
producer:
partition-key-expression: payload # 配置分区键的表达式规则
partition-count: 2 # 配置消息分区的数量
消费者1 application.yml配置
server:
port: 8002 # 端口
spring:
application:
name: stream-consumer # 应用名称
rabbitmq:
host: 127.0.0.1 # 服务器 IP
port: 5672 # 服务器端口
username: guest # 用户名
password: guest # 密码
virtual-host: / # 虚拟主机地址
cloud:
stream:
instance-count: 2 # 消费者总数
instance-index: 0 # 当前消费者的索引
bindings:
# 消息接收通道
smsEmail_in:
destination: sourceMsg # 绑定的交换机名称
group: A
consumer:
partitioned: true # 开启分区支持
消费者2 application.yml配置
server:
port: 8003 # 端口
spring:
application:
name: stream-consumer-2 # 应用名称
rabbitmq:
host: 127.0.0.1 # 服务器 IP
port: 5672 # 服务器端口
username: guest # 用户名
password: guest # 密码
virtual-host: / # 虚拟主机地址
cloud:
stream:
instance-count: 2 # 消费者总数
instance-index: 1 # 当前消费者的索引
bindings:
# 消息接收通道
smsEmail_in:
destination: sourceMsg # 绑定的交换机名称
group: A
consumer:
partitioned: true # 开启分区支持
测试
生产者一下子发送10条,只有其中一个消费者可以收到10条
另外
partition-key-expression 的值也可以为 headers["xxx"],将由 MessageBuilder 类的 setHeader() 方法完成赋值
source.sendSmsAndEmailOutput().send(MessageBuilder
.withPayload(message)
.setHeader("xxx",0).build());