Twilio批量调度十万量级短信时网站卡顿的解决方案求助
Twilio Notify弃用与批量调度短信性能问题解决方案
Twilio Notify弃用说明
Twilio官方宣布:“我们计划于2023年10月23日终止(弃用)Notify产品。”可参考官方迁移指南完成过渡。
Twilio Notify的短信场景可由Twilio SMS API完美替代,该API支持调度最多500,000条消息。
问题描述
用户当前使用的调度代码如下:
$sendAt = (new DateTime())->add(new DateInterval('PT61M')); $msg= "Hi, Bonanza sale !"; foreach ($sendto_leads as $lead) // $sendto_leads 为所有目标电话号码集合 { $to=trim($lead['phone']); $message = $client->messages->create( $to, [ "messagingServiceSid" => "###########################", "body" => $msg, "sendAt" => $sendAt->format('c'), "scheduleType" => "fixed", ] ); }
该代码在处理10、50、100条号码时运行正常,但处理10000条号码时会出现网站变慢、浏览器长时间加载的情况。
问题核心原因
当前代码采用同步循环调用Twilio API的逻辑,每发送一条短信都需要等待Twilio服务器返回响应后,才会处理下一条请求。10000次同步请求会持续占用Web进程,导致前端请求被阻塞,网站无法及时响应用户操作。
解决方案
1. 将调度任务迁移至后台队列
把短信调度逻辑从Web请求流程中剥离,交给后台队列异步执行:
- 以Laravel框架为例,可创建独立的短信调度任务类,将目标号码、消息内容、发送时间等参数传入任务,再通过
dispatch()方法将任务推入队列。 - 后台队列进程会异步处理这些任务,Web请求只需触发任务即可立即响应前端,彻底避免页面卡顿。
示例代码(Laravel队列任务):
// 定义队列任务类 class ScheduleSms implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; protected $phoneNumbers; protected $message; protected $sendAt; public function __construct(array $phoneNumbers, string $message, DateTime $sendAt) { $this->phoneNumbers = $phoneNumbers; $this->message = $message; $this->sendAt = $sendAt; } public function handle(Twilio $client) { foreach ($this->phoneNumbers as $phone) { $client->messages->create( trim($phone), [ "messagingServiceSid" => "###########################", "body" => $this->message, "sendAt" => $this->sendAt->format('c'), "scheduleType" => "fixed", ] ); } } } // 在业务逻辑中触发任务 $sendAt = (new DateTime())->add(new DateInterval('PT61M')); $msg = "Hi, Bonanza sale !"; $phoneNumbers = array_column($sendto_leads, 'phone'); dispatch(new ScheduleSms($phoneNumbers, $msg, $sendAt));
2. 使用异步HTTP请求批量处理
如果不依赖队列框架,可借助Guzzle等HTTP客户端的异步请求功能,同时发起多个API调用,减少整体等待时间:
use GuzzleHttp\Client; use GuzzleHttp\Promise; $sendAt = (new DateTime())->add(new DateInterval('PT61M'))->format('c'); $msg = "Hi, Bonanza sale !"; $client = new Client([ 'base_uri' => 'https://api.twilio.com/2010-04-01/', 'auth' => ['你的Twilio账户SID', '你的Twilio授权令牌'], ]); $promises = []; // 控制每批次并发数,避免触发API限流 $batchSize = 50; $batches = array_chunk($sendto_leads, $batchSize); foreach ($batches as $batch) { foreach ($batch as $lead) { $to = trim($lead['phone']); $promises[] = $client->postAsync('Accounts/你的Twilio账户SID/Messages.json', [ 'form_params' => [ 'MessagingServiceSid' => '###########################', 'To' => $to, 'Body' => $msg, 'SendAt' => $sendAt, 'ScheduleType' => 'fixed', ] ]); } // 等待当前批次异步请求完成后再处理下一批 Promise\Utils::unwrap($promises); $promises = []; }
3. 利用Twilio原生批量调度能力
Twilio支持通过API一次性提交多个调度请求,或使用Messaging Service的批量操作功能,大幅减少HTTP请求次数,提升处理效率。可查阅Twilio官方文档了解具体实现方式。
额外优化建议
- 添加错误捕获:在批量处理逻辑中加入异常捕获,记录发送失败的号码,方便后续重试。
- 监控API速率:查看Twilio的API速率限制规则,确保请求频率在允许范围内,避免被限流。
内容的提问来源于stack exchange,提问作者Tapas Bera
相关产品推荐
相关产品推荐

