Go 队列消费者并发数不是配置越大越能扛一、消费者扩太猛会把下游一起拖下水队列系统常被当成削峰工具。请求进队列消费者慢慢处理看起来很稳。但消费者并发数如果随便拉大就会把数据库、第三方 API、对象存储一起打满。队列只是把压力换了个地方不会凭空消灭压力。消费者设计要按下游容量反推并发。吞吐、失败率、重试策略、单任务耗时都要一起看。并发越大未必越快可能只是失败得更快。我处理过一起典型事故监控看到消息队列积压 80 万条运维第一反应是加消费者。消费者并发从 50 拉到 200CPU 和内存都不是问题。但五分钟之后数据库连接池打满——每条消息处理都要查两次数据库、写一次200 个并发意味着可能同时有 600 个数据库请求。连接池只有 100 个连接瞬间耗尽。然后消息开始大量 ack 超时回到队列消费者重新拉取造成重复消费数据库写入冲突更多。加消费者的结果是积压没减少数据库差点被打挂。真正的解决方案是先限流队列的推送速率等数据库连接池恢复后再逐步放开消费者。二、消费者链路要包含限流、重试和死信一个生产消费者至少要有并发限制、处理超时、重试次数和死信队列。flowchart TD A[消息队列] -- B[消费者拉取] B -- C[并发限制] C -- D[处理任务] D -- E{成功} E --|是| F[确认消息] E --|否| G{可重试} G --|是| H[延迟重试] G --|否| I[死信队列]没有死信队列坏消息会在队列里无限转圈。系统看起来很努力实际在原地打滑。重试策略不能是简单的失败就等一下再试。重试次数要有限制通常 3-5 次重试间隔要指数退避1s → 2s → 4s → 8s并且区分可重试错误和不可重试错误。参数校验失败不应该重试下游临时超时可以重试。重试策略写清后队列的假忙碌会大幅减少。三、用 semaphore 控制本地并发下面示例用信号量限制处理并发。真实项目还要处理 ack、nack 和 shutdown。func Consume(ctx context.Context, msgs -chan Message, limit int, handle func(context.Context, Message) error) { sem : make(chan struct{}, limit) for { select { case -ctx.Done(): return case msg : -msgs: sem - struct{}{} go func(m Message) { defer func() { -sem }() _ handle(ctx, m) }(msg) } } }这里的limit不是随便拍。要根据下游能力、任务耗时和机器资源压测出来。压测时不仅要看多少并发时下游 CPU 到 80%还要看并发每增加 20%P99 延迟增加多少。延迟增长到不可接受时就应该是并发上限而不是等 CPU 打满才停。另外处理超时要独立于并发限制。并发数只控制同时处理的数量但如果某些消息处理超过预期时间比如下游慢查询就应该主动超时取消。goroutine 泄漏最常见的来源就是消费者处理超时后没有及时退出。四、消费者要能优雅停机部署升级时消费者不能直接杀。正在处理的消息要么完成 ack要么安全 nack 回队列。否则会出现重复处理或消息丢失。还要处理幂等。队列消费者天然可能重复消费。业务侧必须有幂等键尤其是写数据库、扣库存、发通知这类动作。只靠队列至少一次语义不能保证业务正确。最后监控要看积压、处理耗时、重试次数和死信数量。只看消费者进程活着没有意义。积压持续升高说明消费能力或下游能力不够。消息可见性超时也要设置合理。处理时间超过可见性超时消息会被其他消费者重复拿到。超时太长失败恢复慢超时太短重复消费多。这个值要按 P99 处理耗时和重试策略来定。还要区分重试队列和主队列。失败消息如果立刻回到主队列会影响正常消息。延迟重试可以放到单独队列避免坏消息一直插队。死信队列也要有人处理不是丢进去就完事。建议给死信队列配置监控死信数量增长要触发告警并安排定期 Review。消费者扩容要看下游指标。队列积压时第一反应不是加消费者而是确认下游是否还有容量。否则扩容只是把事故推进下一层。消费者还要处理消息顺序。有些业务要求同一用户或同一订单按顺序处理此时不能简单并发拉满。可以按 key 分区让同一 key 落到同一处理通道既保留局部顺序又不牺牲全局吞吐。批量消费也要谨慎。批量能提高吞吐但失败时要知道是哪条消息失败。整批重试会放大重复处理逐条确认又会增加开销。批量大小要结合业务幂等和失败率来定。如果失败率低于 1%批量模式可以显著提升吞吐如果失败率超过 5%批量重试的成本可能高于收益。五、总结Go 队列消费者的并发数要按下游容量反推。并发限制、处理超时、重试和死信队列是基本盘。消费者还要支持优雅停机和业务幂等。队列能削峰但不能替系统承受无限压力。消费者设计的目标是有节制地消费不是疯狂地消费然后更快地失败。