PHP怎样实现异步
创始人
2024-12-29 12:42:22
0次

三种实现方式

通用的异步执行文件 exec.php

sleep(8);
$data = "--- type " . date("Y-m-d H:i:s") . " ---\\n";
file_put_contents("../log.txt", $data, FILE_APPEND);

popen

通过 popen() 函数打开进程文件指针,从而能异步执行脚本文件。(只在linux下有效)

pclose(popen("php exec.php &", 'r'));
echo 1;

缺点:只能异步执行本地的脚本文件,不能跨域执行,不能传递参数。

每次执行都会创建新的进程,当并发量高时就创建大量进程,从而造成资源浪费。

curl

应用程序以 curl 发起 http 请求的形式实现异步。但是 curl 请求也需要等待请求返回,程序同样会阻塞,这时我们需要设置 http 请求的超时时间为1s,这样相当于发起了一个 http 请求去执行任务,但是不等待其返回结果,继续向下执行程序,这样就可以实现异步效果。

function asyncCurl($url, $data)
{
    if (is_array($data)) {
        $data = http_build_query($data, null, '&');
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_TIMEOUT, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $result['response'] = curl_exec($ch);
    $result['httpCode'] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    return $result;
}

$url = "";
$data = [];

asyncCurl($url, $data);

echo "OK";

curl 请求实现异步方式的缺陷就是 http 请求的最小超时时间为1s。也就是应用程序无论如何都要等待1s钟以上才能响应(现在 curl 扩展也能支持毫秒级别的超时时间设置,不过毫秒时间的超时很容易造成请求失败)。

fsockopen

fsockopen() 函数用于打开一个网络连接或者一个Unix套接字连接。通过发起 http 通信来实现异步。

从原理上来说与 curl 请求一样。

function sockPost($host, $url, $param)
{
    $port = parse_url($url, PHP_URL_PORT);
    $port = $port ? $port : 80;
    $scheme = parse_url($url, PHP_URL_SCHEME);
    $path = parse_url($url, PHP_URL_PATH);
    $query = http_build_query($param);

    if ($scheme == 'https') {
        $host = 'ssl://' . $host;
    }
    $fp = fsockopen($host, $port, $error_code, $error_msg, 1);
    if (!$fp) {
        return array('error_code' => $error_code, 'error_msg' => $error_msg);
    } else {
        stream_set_blocking($fp, 0);
        stream_set_timeout($fp, 10);
        $header = "GET $path" . "?" . "$query" . " HTTP/1.1\\r\\n";
        $header .= "Host: $host\\r\\n";
        $header .= "Connection: close\\r\\n\\r\\n";//长连接关闭
        fwrite($fp, $header);
        usleep(2000); // 延时,防止在nginx服务器上无法执行成功
        fclose($fp);
        return array('error_code' => 0);
    }
}

$host = "127.0.0.1";
$url = "/exec.php";
$param = [];
$result = sockPost($host, $url, $param);
var_dump($result);

fsockopen 方式相比 curl 更复杂,需要自己拼接处 http 请求的 header 部分。在 curl 不支持毫秒级超时之前 fsockopen 方式无疑是最佳选择。

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...