如何用PHP高效发送大量GET请求?批量短信模块开发疑问
解决PHP短信群发效率问题的实用方案
嘿,针对你开发的PHP管理员短信跟进模块在批量发送时遇到的效率瓶颈,我整理了几个实战中好用的解决思路:
1. 用Curl并行请求替代同步的file_get_contents
file_get_contents是同步阻塞的——发一条短信就得等请求完成才能发下一条,批量发送时效率极低。改用curl_multi系列函数实现并行请求,能同时发起多个API调用,大幅缩短总耗时。
举个简单的示例代码:
// 待发送的手机号列表 $phoneNumbers = ['138xxxxxxx', '139xxxxxxx', ...]; $message = "你的跟进短信内容"; $apiUrl = "sms_api_url?credentials&phone=%s&msg=%s"; // 初始化curl多句柄 $mh = curl_multi_init(); $handles = []; foreach ($phoneNumbers as $phone) { $url = sprintf($apiUrl, urlencode($phone), urlencode($message)); $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_multi_add_handle($mh, $ch); $handles[] = $ch; } // 执行并行请求 $running = null; do { curl_multi_exec($mh, $running); curl_multi_select($mh); } while ($running > 0); // 处理结果并清理句柄 foreach ($handles as $ch) { $response = curl_multi_getcontent($ch); // 这里可以记录发送结果(成功/失败) curl_multi_remove_handle($mh, $ch); curl_close($ch); } curl_multi_close($mh);
2. 优先使用API的批量发送接口(如果支持)
先去查一下你用的短信API文档,看看有没有批量发送的接口——比如允许一次传入多个手机号(用逗号分隔或者数组参数),这样只需要发起1次请求就能完成多条短信发送,效率提升是数量级的。这是最优解,比任何客户端优化都管用。
3. 引入队列系统处理超大量发送
如果要发送几百甚至上千条短信,直接在Web请求里处理很容易超时,还会影响用户体验。建议用队列异步处理:
- 第一步:把需要发送的手机号、消息内容存入队列(比如用Redis队列,或者数据库表作为简易队列)
- 第二步:写一个CLI脚本(命令行运行的PHP脚本),后台循环从队列里取出任务,逐条/批量发送
- 额外好处:可以轻松实现失败重试、发送进度统计,还能避免Web请求超时
简易数据库队列示例:
// 存入队列(Web端调用) $pdo = new PDO('mysql:host=localhost;dbname=your_db', 'user', 'pass'); $sql = "INSERT INTO sms_queue (phone, message, status) VALUES (?, ?, 'pending')"; $stmt = $pdo->prepare($sql); foreach ($phoneNumbers as $phone) { $stmt->execute([$phone, $message]); } // 消费队列的CLI脚本 while (true) { $stmt = $pdo->query("SELECT * FROM sms_queue WHERE status='pending' LIMIT 10 FOR UPDATE"); $tasks = $stmt->fetchAll(PDO::FETCH_ASSOC); if (empty($tasks)) { sleep(5); // 没有任务就休眠5秒再查 continue; } // 这里用curl_multi批量处理这10条任务 // ...(参考上面的curl_multi代码) // 更新任务状态为success/failed foreach ($tasks as $task) { $updateStmt = $pdo->prepare("UPDATE sms_queue SET status=? WHERE id=?"); $updateStmt->execute([$sendResult ? 'success' : 'failed', $task['id']]); } }
4. 小幅度优化file_get_contents(应急方案)
如果暂时不想换Curl,可以通过修改流上下文参数来优化file_get_contents的性能,比如缩短超时时间、开启持久连接:
$context = stream_context_create([ 'http' => [ 'timeout' => 5, // 设置5秒超时,避免长时间等待 'keep_alive' => true, // 开启持久连接 ] ]); $result = file_get_contents($url, false, $context);
不过这个优化的效果有限,只适合小批量发送的场景。
额外注意事项
- 务必查看短信API的频率限制:很多API会限制单位时间内的请求次数,别因为批量发送触发限流导致失败
- 跨域问题:虽然你用GET请求测试正常,但批量发送时要确保API服务器允许你的域名发起大量请求,避免被跨域策略拦截
内容的提问来源于stack exchange,提问作者Danish Nayeem
相关产品推荐
相关产品推荐

