PHP批量POST首选cURL扩展,因其可控性强、健壮性高;应避免file_get_contents的简单用法,慎用并发控制,务必检查错误与HTTP状态码。

用 cURL 发送批量 POST 请求最稳
PHP 自带的 cURL 扩展是批量发 POST 的首选,比 file_get_contents 配 stream_context_create 更可控、更健壮。尤其在需要设置 header、cookie、超时、证书或复用连接时,cURL 几乎是唯一靠谱的选择。
常见错误现象:用 file_get_contents 发送 JSON 数据却没设 Content-Type: application/json,服务端收不到 $_POST;或者并发量稍大就卡死、超时、连接被重置。
- 每次请求前调用
curl_init(),结束后必须curl_close()(除非你明确复用句柄) - 批量发送时,不要在循环里反复
curl_setopt($ch, ...)设置相同参数(如CURLOPT_RETURNTRANSFER),可提前统一配置 - 务必设置
CURLOPT_TIMEOUT和CURLOPT_CONNECTTIMEOUT,否则一个慢接口会拖垮整个批次 - 若目标接口要求 JSON,用
json_encode($data)后传给CURLOPT_POSTFIELDS,并手动加Content-Typeheader
并发控制别硬扛,用 curl_multi_exec 管理多请求
直接 for 循环逐个 cURL 是最简单的方式,但效率低;全开 100 个并发又容易触发目标服务器限流或本地端口耗尽。折中方案是用 curl_multi_exec 做轻量级并发(比如同时跑 5–10 个)。
它不是“多线程”,而是基于 select/poll 的 I/O 复用,PHP 单进程就能管理多个连接,不阻塞、不 fork、不依赖扩展。
立即学习“PHP免费学习笔记(深入)”;
- 先用
curl_multi_init()创建 multi 句柄 - 每个请求单独
curl_init(),配置好后用curl_multi_add_handle()加入队列 - 用
curl_multi_exec()轮询执行,配合curl_multi_select()避免忙等 - 响应返回后,用
curl_multi_getcontent()取 body,再用curl_multi_remove_handle()清理 - 注意:不能在 multi 模式下用
curl_setopt($ch, CURLOPT_HEADERFUNCTION, ...)这类回调,会冲突
file_get_contents + stream_context_create 仅适合简单场景
如果你只是发几个表单数据(application/x-www-form-urlencoded)、没认证、没重试、不关心响应头,且确定目标接口很稳定,那 file_get_contents 写起来确实快。
但一旦出错——比如返回 400 却没报错、body 是空字符串、header 里有跳转但没跟随——你就得自己补一堆逻辑,反而更费劲。
- 必须显式设置
http选项数组,method设为'POST',content是http_build_query($data)或 JSON 字符串 -
header项要手拼,例如"Content-Type: application/json\r\n",漏了\r\n会失败 - 无法获取响应状态码(
$http_response_header可读,但不稳定),也不能设 cookie jar 或自动跳转 - PHP 8.0+ 中默认禁用
allow_url_fopen,该方式直接不可用
调试阶段一定要检查 curl_error 和 HTTP 状态码
批量发送时,某个请求失败往往悄无声息——curl_exec() 返回 false,但你不检查 curl_errno() 就以为是业务失败;或者返回了 200,但 body 是 {"code":500,"msg":"xxx"},你却当成成功处理了。
- 每次
curl_exec()后立即调用curl_error($ch)和curl_getinfo($ch, CURLINFO_HTTP_CODE) - 对非 2xx 状态码(尤其是 429、502、503)做区分处理:429 要退避重试,502/503 可能需跳过或延后重发
- 记录失败请求的原始参数和完整响应(包括 header),别只记一句 “请求失败”
- 线上运行时,避免把
curl_error直接打到日志里(可能含敏感信息),至少脱敏 URL 和 post data
真正难的不是发出去,而是发得稳、收得准、错得明。批量 POST 的坑不在语法,而在连接管理、错误归因和节流策略上——这些地方一松懈,半夜就会收到告警。











