PHP 的异步执行

Ty
Ty
2022-03-12 / 0 评论 / 43 阅读 / 正在检测是否收录...

前言

PHP

客户端与服务器端是通过 HTTP 协议 进行连接通讯,客户端发起请求,服务器端接收到请求,服务端再执行处理,并返回处理结果。

有时服务器需要执行很耗时的操作,这个操作的结果并不需要立即返回给客户端。但因为 php 是同步执行的,所以客户端需要等待一项操作处理完才可以进行下一步操作。

因此,对于耗时的操作适合异步执行。服务器接收到请求后,处理完客户端需要的数据就立即返回,再异步在服务器执行耗时的操作。

使用 Ajax

在服务器返回的页面中插入 Ajax 代码实现异步执行。

$.get('do.php' , { name: 'fdipzone' } );

使用 <img> 标记

在服务器返回的页面中插入 <img> 标签,将 src 参数设定为需要异步执行的操作。

<img src="do.php">

使用 fsockopen 

fsockopen 是 PHP 异步执行最好的选择,此函数的功能为初始化一个套接字连接到指定主机,默认情况下将以阻塞模式开启套接字连接。当然你可以通过stream_set_blocking()将它转换到非阻塞模式。这是关键。所以,思路就是开启一个非阻塞的套接字连接到本机,本机收到之后作一些耗时处理。

$fp = fsockopen($php_Path,80);
if (!$fp) {
    LMLog::error("fsockopen:err" );
} else {
    $out = "GET /album/action/album_write_friends_thread_record.php?key=&u=   HTTP/1.1\r\n";
    $out .= "Host: ".$php_Path."\r\n";
    $out .= "Connection: Close\r\n\r\n";
    stream_set_blocking($fp,true);
    stream_set_timeout($fp,1);
    fwrite($fp, $out);
    usleep(1000); //这里非常关键,它能保证这个请求能发出去
    fclose($fp);
}

使用 popen

如果要实现多进程的功能,毫无疑问我们会选择官方提供的 pcntl 扩展, PHP 默认会安装 pcntl 扩展,如果代码运行提示找不到 pcntl 扩展,可自行到 php-src 下载,选择好版本安装即可。

<?php
class Arrow{

    static $instance;

    /**
     * @return static
     */
     public static function getInstance(){
        if (null == Arrow::$instance)
            Arrow::$instance = new Arrow();
        return Arrow::$instance;
    }

    public function run($rb){

        $pid = pcntl_fork();
        if($pid > 0){
            pcntl_wait($status);
        }elseif($pid == 0){
            $cid = pcntl_fork();
            if($cid > 0){
                exit();
            }elseif($cid == 0){
                $rb();
            }else{
                exit();
            }
        }else
        {
           exit();
        }

    }
}

$time_out = 30;
Arrow::getInstance()->run(function() use ($time_out){
    //这里写我们要执行的代码
    sleep($time_out);
});
1

评论 (0)

取消