转自https://www.awaimai.com/660.html
为让 PHP 在后端处理长时间任务时不阻塞,快速响应页面请求,可以有如下措施:
1 使用 fastcgi_finish_request()
如果 PHP 与 Web 服务器使用了PHP-FPM(FastCGI 进程管理器),那通过fastcgi_finish_request()函数能马上结束会话,而 PHP 线程可以继续在后台运行。
echo "program start...";
file_put_contents('log.txt','start-time:'.date('Y-m-d H:i:s'), FILE_APPEND);
fastcgi_finish_request();sleep(1);
echo 'debug...';
file_put_contents('log.txt', 'start-proceed:'.date('Y-m-d H:i:s'), FILE_APPEND);
sleep(10);
file_put_contents('log.txt', 'end-time:'.date('Y-m-d H:i:s'), FILE_APPEND);
2 使用 fsockopen()
使用fsockopen()打开一个网络连接或者一个Unix套接字连接,再用stream_set_blocking()非阻塞模式请求:
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp) { die('error fsockopen');}// 转换到非阻塞模式
stream_set_blocking($fp, 0);
$http = "GET /save.php / HTTP/1.1\r\n";
$http .= "Host: www.example.com\r\n";
$http .= "Connection: Close\r\n\r\n";fwrite($fp, $http);fclose($fp);
3 使用 cURL
利用cURL中的curl_multi_*
函数发送异步请求
$time = time();// 创建一对cURL资源
$ch1 = curl_init();
$ch2 = curl_init();
$ch3 = curl_init();// 设置URL和相应的选项
curl_setopt($ch1, CURLOPT_URL, "http://test.xtgxiso.cn/sleep1.php");
curl_setopt($ch1, CURLOPT_HEADER, 0);
curl_setopt($ch2, CURLOPT_URL, "http://test.xtgxiso.cn/sleep2.php");
curl_setopt($ch2, CURLOPT_HEADER, 0);
curl_setopt($ch3, CURLOPT_URL, "http://test.xtgxiso.cn/sleep3.php");
curl_setopt($ch3, CURLOPT_HEADER, 0);// 创建批处理cURL句柄
$mh = curl_multi_init();// 增加2个句柄
curl_multi_add_handle($mh,$ch1);
curl_multi_add_handle($mh,$ch2);
curl_multi_add_handle($mh,$ch3);
$running=null;// 执行批处理句柄
do { usleep(10000); curl_multi_exec($mh,$running);} while ($running > 0);// 关闭全部句柄
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_remove_handle($mh, $ch3);
curl_multi_close($mh);
echo "\n total time : ".(time()-$time)."\n";
5 使用缓存和队列
使用redis等缓存、队列,将数据写入缓存,使用后台计划任务实现数据异步处理。
6 调用系统命令
极端的情况下,可以调用系统命令,可以将数据传给后台任务执行