如何在PHP中使用swoole

294 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第19天,点击查看活动详情

1.swoole启动关闭方案

1.swoole如何在后台运行

(1)nohup php server.php &     或者   screen php server.php
(2)设置daemonize => 1时,程序将转入后台作为守护进程运行。长时间运行的服务器端程序必须启用此项

  • 启用守护进程后,标准输入和输出会被重定向到log_file
  • 如果未设置log_file,将重定向到/dev/null,所有打印屏幕的信息都会被丢弃

2.手动关闭swoole

# 先查看端口对应的进程 id
netstat -tunlp|grep 9501

### 结果 tcp        0      0 0.0.0.0:9400            0.0.0.0:*               LISTEN      2750/php

# kill 进程 id 就完事了
kill -9 2750

# 查看进程信息 (当然在 kill 之前查看)
ps -ef|grep 2750

2.swoole服务端主动推送消息

<?php
//创建WebSocket Server对象,监听0.0.0.0:9502端口
$ws = new Swoole\WebSocket\Server('0.0.0.0', 9503);
//监听WebSocket连接打开事件
$ws->on('open', function ($ws, $request) {
    $fd=$request->fd;
    var_dump($request->fd, $request->server);
    $ws->push($request->fd, "hello, welcome\n");
});

//监听WebSocket消息事件
$ws->on('message', function ($ws, $frame) {
//echo "Message: {$frame->data}\n";
    $ws->push($frame->fd, "服务端返回:{$frame->data}");
   
});
//第一种方式:通过curl调用swoole.xian008.com:9501(客户端websocket连接地址)
$ws->on('request', function (Swoole\Http\Request $request, Swoole\Http\Response $response) {
    global $ws;//调用外部的server
    //$server->connections 遍历所有websocket连接用户的fd,给所有用户推送
    foreach ($ws->connections as $fd) {
        // 需要先判断是否是正确的websocket连接,否则有可能会push失败
        if ($ws->isEstablished($fd)) {
            $ws->push($fd, $request->post['message']);
        }
    }
});
第二种方式:通过redis订阅来实现
$process = new Swoole\Process(function ($process)use($ws) {
        echo 'process';
        $redis = new \Redis();
        $redis->connect('127.0.0.1',6379);
        $redis->auth('xiaocinao');
        $redis->subscribe(['name'],function ($redis,$channel,$msg)use($ws){
        $ws->push(1,$msg);
        });
        });

//监听WebSocket连接关闭事件
$ws->on('close', function ($ws, $fd) {
    echo "client-{$fd} is closed\n";
});
$ws->addProcess($process);
$ws->start();

3.创建websocket--systemctl自定义启动服务

在/lib/systemd/system/目录或者/etc/systemd/system/目录下创建service结尾的文件如swoole.service文件

[Unit]

Description=swoole websocket

[Service]

Type=simple
#EnvironmentFile=/etc/systemd/test.conf

ExecStart=/usr/bin/php /home/swoole/extend/lib/Swoole.php

ExecReload=/bin/kill --USR1 $MAINPID

ExecStop=/bin/kill -SIGTERM $MAINPID

[Install]

WantedBy=multi-user.target 

$ MAINPID是服务的systemd变量,它指向主应用程序的PID。

4.创建php脚本来启动关闭websocket服务

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2020/11/24
 * Time: 17:26
 */
//exec可以把执行的结果全部返回到$output函数里(数组),$status是执行的状态 0为成功 1为失败

$order=$argv[1];
$sh2='/usr/bin/php /home/swoole/extend/lib/Swoole.php';
switch ($order){
    case 'start':
        exec($sh2,$res,$rc);
        if($rc==0){
            echo 'success';
        }
          break;
    case 'stop':
        $pid=swoole();
        \Swoole\Process::kill($pid, $signo = SIGTERM);
        echo 'stop';
        break;
    case 'restart':
        $pid=swoole();
        \Swoole\Process::kill($pid, SIGUSR1);
        echo 'restart';
        break;
}
function swoole(){
    $sh = 'pgrep -f swoole_master';
    exec($sh,$res,$rc);
    $pid=$res[0];
    return $pid;
}

5.进程、线程、协程

进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。
线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程也由操作系统调度。
协程和线程一样共享堆,不共享栈,协程由程序员在代码里调度。(援引网络博文)

6.进程/线程结构图