curl 实现异步 php
使用 curl 实现 PHP 异步请求
在 PHP 中,curl 默认是同步执行的,但可以通过一些技巧实现类似异步的效果。以下是几种常见的方法:
设置 CURLOPT_TIMEOUT 和 CURLOPT_CONNECTTIMEOUT
通过设置极短的超时时间,可以让 curl 请求快速返回,不阻塞主进程:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://example.com/async");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 1); // 1秒超时
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1);
curl_exec($ch);
curl_close($ch);
使用 curlmulti* 函数组
curlmulti* 允许同时处理多个 curl 请求,虽然不是真正的异步,但能提高并发效率:
$mh = curl_multi_init();
$ch1 = curl_init("http://example.com/1");
$ch2 = curl_init("http://example.com/2");
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);
$running = null;
do {
curl_multi_exec($mh, $running);
} while ($running);
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);
结合 fsockopen 实现真正异步
使用 fsockopen 可以建立非阻塞连接:
$fp = fsockopen("example.com", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)";
} else {
$out = "GET /async.php HTTP/1.1\r\n";
$out .= "Host: example.com\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
fclose($fp);
}
使用 ignore_user_abort 和 fastcgi_finish_request
在 PHP-FPM 环境下可以这样实现:
echo "Request processing started";
fastcgi_finish_request();
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://example.com/async");
curl_exec($ch);
curl_close($ch);
通过队列系统实现
更健壮的方式是使用消息队列:
// 生产者
$queue = new Redis();
$queue->connect('127.0.0.1', 6379);
$queue->lPush('async_requests', json_encode(['url' => 'http://example.com']));
// 消费者 (单独进程)
while(true) {
$task = $queue->rPop('async_requests');
if ($task) {
$data = json_decode($task, true);
$ch = curl_init($data['url']);
curl_exec($ch);
curl_close($ch);
}
sleep(1);
}
每种方法都有其适用场景,需要根据具体需求选择。对于简单的异步需求,短超时或 fsockopen 方法足够;对于高并发场景,建议使用队列系统。







