外观
ActiveMQ Artemis 陷阱与检查表
本页结论:Artemis 的大多数事故来自把它当「JMS 版 Kafka」(期待回放/分区)或忽视服务端默认值(10 次重投、BLOCK 背压、确认会话类型)——这四类边界必须在设计阶段写进方案。
默认值陷阱
| 默认行为 | 风险 | 建议 |
|---|---|---|
max-delivery-attempts 默认 10 | 毒消息重投 10 次才进死信,且多数部署没配死信地址 → 消息消失或长期抖动 | 按业务设重试上限,每个业务地址都显式配 dead-letter-address |
| 无死信地址配置 | 耗尽重试的消息被直接丢弃 | DLQ 地址 + 深度告警是标配 |
AUTO_ACKNOWLEDGE 会话 | 回调抛异常前已自动确认 → 业务失败即丢消息 | 生产一律 CLIENT_ACKNOWLEDGE 或事务会话 |
| 地址自动创建 | 首个使用者的类型决定 anycast/multicast,拼写错误会留下一堆野地址 | 生产显式建地址,关闭或收紧自动创建 |
address-full-policy=PAGE 无上限感知 | 积压静默分页到磁盘,消费越来越慢才被发现 | 深度/分页状态告警先行 |
| BLOCK 策略 | 积压时生产者线程全部阻塞,故障扩散到上游服务 | 明确选择 PAGE/FAIL 并压测 |
错误类比(常见误区)
- 「Artemis 可以当 Kafka 用」——错在存储模型:确认即删除,没有位点、没有回放;需要重放必须上游重发(见 存储与高可用)。
- 「多消费者就有分区级顺序」——竞争消费打破全局顺序;同键顺序要用
_AMQ_GROUP_ID粘连,且组数远多于消费者数才均衡。 - 「Artemis 就是 ActiveMQ(Classic)」——两套代码库:配置格式、客户端、调优参数全不同;Classic 的 retroactive 订阅等特性在 Artemis 无直接对应。
- 「集群能扩单队列吞吐」——集群分布的是多个队列;单个队列仍在单节点,吞吐上限不变。
- 「事务会话就是端到端恰好一次」——Broker 内原子不等于业务端到端:业务库、下游调用仍需幂等与补偿。
- 「重投会重置计数,如果换了消费者」——投递计数按消息累计,跨消费者共享。
不适用场景
- 长期保留与按时间回放:队列模型不支持,用分区日志产品。
- 单队列超高吞吐(>单节点能力):无分区扩展路径,需业务拆队列或换日志型 Broker。
- 海量小 Topic 的 Pub/Sub 树(IoT 百万主题):MQTT 接入可用但路由/安全模型为地址设计,超大规模主题空间非其主场。
- 多租户平台:无内建租户模型,需实例级隔离。
生产检查表
- [ ] 每个业务地址显式声明路由类型(anycast/multicast),关闭不受控的自动创建。
- [ ] 消费会话为
CLIENT_ACKNOWLEDGE或事务;AUTO_ACKNOWLEDGE未出现在生产代码。 - [ ] 每个地址有明确的重试上限、重投间隔与死信地址;DLQ 深度告警已配置。
- [ ] 消费端幂等键已就位(重投必然发生,问题只是何时)。
- [ ] 生产端重发带
_AMQ_DUPL_ID,去重缓存大小按重试窗口估算。 - [ ] journal 盘为低延迟本地盘(或已评估云盘 fsync 特性);ASYNCIO/NIO 选择经过压测。
- [ ] 高可用模式已选(复制对 + 仲裁,或共享存储),并演练过故障切换与客户端重连。
- [ ] 安全:认证启用、地址级角色授权最小化;61616/8161 不对公网。
- [ ] 监控:队列深度、投递/确认速率差、分页状态、DLQ/过期地址深度、连接与消费者数。
- [ ] 容量评估以「单队列单节点」为前提,热点已按业务键拆队列或用 Message Group。