在使用 PHP 进行 HTTP 请求时,cURL 是最常用的扩展之一。它功能强大,支持各种协议,但在使用过程中也存在许多潜在的误区。特别是在 curl_close() 和 curl_setopt() 的配合使用上,很多开发者并未意识到它们对性能的影响。本文将深入分析这些常见误区,并提供优化建议。
这是最普遍的误区。许多开发者习惯在每次请求时都调用:
$ch = curl_init();
// 设置各种选项
curl_setopt($ch, CURLOPT_URL, 'https://gitbox.net/api/data');
$response = curl_exec($ch);
curl_close($ch);
虽然这样写代码清晰直观,但却忽略了性能问题。频繁地 curl_init() 和 curl_close() 会导致资源频繁地分配和回收,增加了系统开销。
优化建议:如果在短时间内需要发送多个请求,推荐复用同一个 cURL 句柄,只修改必要的参数即可。
$ch = curl_init();
$urls = [
'https://gitbox.net/api/data1',
'https://gitbox.net/api/data2',
'https://gitbox.net/api/data3',
];
foreach ($urls as $url) {
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
// 处理 $response
}
curl_close($ch);
一些开发者在复用句柄时为了“干净”,每次都调用 curl_reset($ch),认为这是一种安全做法。实际上,curl_reset 会将所有设置都清除,相当于重新初始化,不如手动设置必要参数更高效。
建议:只更新会变化的选项,如 CURLOPT_URL、CURLOPT_POSTFIELDS,而非重置所有选项。
有些代码库中会遗漏 curl_close(),尤其是发生异常时没有在 finally 块中关闭句柄,长期运行会造成内存泄漏。
建议:始终确保使用完毕后释放资源。推荐使用如下结构:
$ch = curl_init();
try {
curl_setopt($ch, CURLOPT_URL, 'https://gitbox.net/api/user');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
// 处理 $response
} finally {
curl_close($ch);
}
在使用 curl_multi_* 执行并发请求时,开发者有时会在任务执行前或执行中意外关闭句柄,导致请求失败。
正确方式:确保所有子请求完成后,再调用 curl_close():
$mh = curl_multi_init();
$chs = [];
$urls = [
'https://gitbox.net/api/a',
'https://gitbox.net/api/b',
];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch);
$chs[] = $ch;
}
do {
$status = curl_multi_exec($mh, $active);
curl_multi_select($mh);
} while ($active && $status == CURLM_OK);
foreach ($chs as $ch) {
$response = curl_multi_getcontent($ch);
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
PHP 的 cURL 支持连接复用(Connection Reuse),但需要服务器端支持 Keep-Alive,同时还需开启:
curl_setopt($ch, CURLOPT_FORBID_REUSE, false);
还可启用 CURLOPT_TCP_KEEPALIVE 相关设置,在长连接服务中优化性能。
有些选项如果默认就是你所需的行为,没必要每次都显式设置。例如:
// 不必每次都设为 false,因为这是默认值
curl_setopt($ch, CURLOPT_HEADER, false);
减少不必要的 curl_setopt 调用,有助于提升脚本执行效率。
DNS 查询是 HTTP 请求中的性能瓶颈之一。可以通过设置自定义解析或使用缓存机制优化:
curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 300);
或设置本地解析:
curl_setopt($ch, CURLOPT_RESOLVE, ['api.gitbox.net:443:192.168.0.1']);
在现代服务器支持的前提下,启用 HTTP2 能带来更高的并发性和更快的请求响应速度:
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_close() 看似只是简单的资源释放函数,但与 curl_setopt() 的配合使用,却直接影响着程序的性能和稳定性。养成良好的使用习惯,不仅可以避免内存泄漏,还能显著提升请求效率。对于高并发场景,合理复用句柄、精简设置、管理连接生命周期,都是 PHP cURL 调优的关键所在。