通过AWS SNS短时间发送大量短信的限流问题及实现方案咨询
方案对比与最优实践
现有临时方案的问题
仅靠cronjob重试完全不适合作为长期方案,核心缺陷如下:
- 无法满足实时性要求:cron间隔设置过短会导致请求集中发送,依然大概率触发限流;间隔设置过长会导致短信发送延迟达到分钟级,不符合数秒内触达的需求。
- 缺少幂等控制:如果没有配套的去重逻辑,很容易出现重复给用户发短信的问题,严重影响用户体验。
- 可扩展性差:随着待发送短信的积压,cron单次执行的负载会持续升高,极易出现执行超时、内存溢出等问题。
应用侧硬编码延迟的适用场景
应用内实现延迟/限流只适合单实例部署、业务规模极小、可靠性要求不高的场景,缺陷也非常明显:
- 多实例部署时无法做全局速率控制,每个实例单独控制20/s的话,总请求量还是会超过下游限制。
- 应用发布、重启时,内存中暂存的待发送请求会直接丢失,无法保证消息必达。
- 限流逻辑和业务代码耦合,如果后续有其他业务模块需要调用短信发送能力,需要重复实现限流逻辑,冗余度高。
SQS队列控频方案(最优解)
搭配AWS SQS做流量管控是当前场景最合理的实现方式,优势如下:
- 消息可靠性有保障:所有待发送短信先写入SQS队列,默认最多保留14天,不会因为应用重启、发布丢失消息。
- 速率控制简单精准:你可以单独部署消费worker,控制全局消费速率稳定在20/s即可,比如每批量拉取20条消息处理完成后,等待1秒再拉下一批,实现成本极低。如果后续下游服务商的限流阈值上调,只需要调整消费端的速率参数即可,不需要修改上游业务代码。
- 异常处理更灵活:可以搭配SQS死信队列,把连续多次发送失败的消息(比如手机号格式错误、空号等永久失败的请求)单独归集处理,避免无效重试占用带宽。
额外优化建议
- 所有短信请求增加唯一消息ID,消费端发送前先校验该ID是否已有发送成功的记录,避免重试时重复发送。
- 可以在消费侧实现简单的退避策略,触发限流时自动等待几百毫秒再重试,减少不必要的失败请求。
内容的提问来源于stack exchange,提问作者Heng Zhi Feng
相关产品推荐
相关产品推荐

