发布订阅与投递概念
从消息、主题、消费者到确认与幂等,理解统一接口背后的不同投递模型。
消息把“提出工作”和“执行工作”分开。生产者发送事实或请求,消费者在自己的执行环境处理它。这样可以缓冲流量和分离生命周期,但也引入延迟、重复和部分失败;调用接口成功不再等于业务已经完成。
消息中的身份
连接名
应用选择一个配置好的队列连接
驱动名、物理队列名
Topic
消息路由或订阅范围
不同 Broker 的通配符不通用
Group
驱动特定的分组参数
Kafka 消费组、RabbitMQ exchange、ZeroMQ 前缀含义不同
Identifier
某次发布或协议报文的标识
不一定是稳定业务去重键
Identity
生产者实例等身份信息
不能直接等同于已认证用户
Tags
扩展筛选或元数据
部分驱动不用于路由
Data
业务负载
需要应用约定编码、结构及版本
建议在业务负载中包含稳定事件标识、事件类型和必要的版本信息。重试同一业务事件时保留业务标识,避免由于适配器每次生成新的发送标识而重复执行副作用。
广播与竞争消费
广播让多个订阅者各自看到同一事件,适合缓存失效或状态通知。竞争消费让一组处理者分担工作,适合异步任务。两者都可能表现为“订阅同一个主题”,实际行为必须结合驱动及分组配置判断。
例如 Kafka 通过消费组分配分区;ZeroMQ 的最多一次通道是广播,至少一次通道在在线消费者之间竞争投递。业务不能仅替换连接驱动就假定扩容后的消费数量和顺序完全一致。
可靠性与确认
“最多一次”允许消息丢失但不主动重试;“至少一次”允许重复以减少未完成投递丢失;“恰好一次”只有在明确限定的协议与状态范围内才有意义。MQTT QoS 2 的协议保证不能自动覆盖消费者写数据库或调用第三方接口的副作用。
确认是消费者告诉消息系统:这条消息的责任已经处理到约定阶段。框架使用 Message.AcknowledgeAsync 表达该动作;其具体效果可能是提交位点、发送 ACK,或在没有确认协议时没有效果。处理器正常返回不能普遍视为确认。
关于各驱动的实际返回值、确认条件和后台行为,见消息队列及可靠投递。
顺序与并发
网络接收顺序、处理开始顺序、业务提交顺序是三个不同概念。并发处理、重试和跨分区消费都可能改变完成顺序。需要同一订单有序处理时,应明确路由键、分区/消费者模型及业务版本检查,不能只依赖发送端逐条调用。
背压表示处理速度跟不上时限制上游继续进入,防止无限堆积。它可能体现为有界内存队列、暂停读取或 Broker 中积压。应监控积压数量和最老消息年龄;单纯提高并发可能把压力转移到数据库。
从一个小闭环开始
先用两个客户端、独立主题和少量消息验证发送、接收及确认。然后让处理器故意失败、断开客户端并重新连接,观察消息是否重投及标识是否保持。最后才加入真实业务副作用。
应用应独立定义:重复如何识别、失败重试多少次、无法处理的消息如何隔离、停机怎样停止接收并等待在途任务。统一消息接口提供调用边界,不会自动替业务作出这些决定。
最后更新于