php cli编写一个高并发的http服务

php cli编写一个高并发的http服务

php cli编写一个高并发的http服务

大家都知道php的http请求处理脚本是运行在apache或php-fpm中,那么除此之外还有其他吗?有,其实php cli命令行中也是可以响应http请求并处理的,最简单的参照对象就是workman、swoole,php可以监听tcp或udp的端口,实现http协议,今天我们来试一试

<?php
$socket = stream_socket_server("0.0.0.0:8889", $errno, $errstr);
stream_set_blocking($socket, 0);//设置是否阻塞

if (!$socket) {
    echo "$errstr ($errno)<br />\n";
} else {
    while (true) {
        $conn = @stream_socket_accept($socket);//接受客户端的请求

        if ($conn)
        {
            fwrite($conn, '当前时间是 ' . date('n/j/Y g:i a') . "\n");//响应客户端请求
            fclose($conn);

        } else {
            echo "no newSocket\n";
        }
    }
}
?>

上面面是个简单的http监听服务,具体的post、session等处理还需有更进一步的优化,好了,有的人肯定好奇,就这么几句话就实现高并发了?

没那么简单,高并发还需要多个进程来进行处理,php-fpm也不止一个呀,好了,我们来写一个Worker,实现进程自我创建和管理,提高php的并发处理能力,就想餐馆,一个服务员不够就多个嘛

<?php

class Worker
{
    /**
     * version
     * @var string
     */
    const VERSION = '0.0.1';

    /**
     * Emitted when data is received
     * @var callable
     */
    public $onMessage = NULL;

    /**
     * 子进程的数量
     * @var int
     */
    public $count = 1;

    /**
     * Listening socket
     * @var resource
     */
    public $socket = NULL;

    /**
     * Socket name The format is like this 0.0.0.0:8000
     * @var string
     */
    protected $_socketName = '';

    /**
     * 连接socket
     * @var resource
     */
    protected $_connSocket = NULL;

    /**
     * 子进程 pid 数组
     * @var array
     */
    private $forkList = [];

    /**
     * 主进程 ID 文件
     * @var string
     */
    private $masterPidFile = 'master.pid';

    /**
     * 主进程是否停止
     * @var int
     */
    private $masterStop = 0;

    public function __construct($socketName, $options = [])
    {
        $this->_socketName = $socketName;
    }

    public function init()
    {
        $this->parseCommand();
    }

    public function start()
    {
        // 判断当前程序是否已经启动
        $masterPidFileExist = is_file($this->masterPidFile);
        if ($masterPidFileExist) {
            exit("当前程序已经在运行,请不要重启启动
");
        }

        // 保存主进程pid到文件用于stop,reload,status等命令操作
        $masterPid = posix_getpid();
        file_put_contents($this->masterPidFile, $masterPid);


        pcntl_signal(SIGINT, array($this, 'signalHandler'), false);
        pcntl_signal(SIGTERM, array($this, 'signalHandler'), false);
        pcntl_signal(SIGUSR1, array($this, 'signalHandler'), false);

        $this->listen();

        // 创建count个子进程,用于接受请求和处理数据
        while(count($this->forkList) < $this->count) {
            $this->forkWokrer();
        }

        while (true)
        {
            //sleep(1);
            pcntl_signal_dispatch(); // 信号分发
            $status = 0;
            $pid = pcntl_wait($status, WUNTRACED); // 堵塞直至获取子进程退出或中断信号或调用一个信号处理器,或者没有子进程时返回错误
            p...

点击查看剩余70%

{{collectdata}}

网友评论0