Laravel 5.6 中优雅的管理 swoole 进程

1. 创建自定义artisan命令
php artisan make:command SwooleManger //默认在app/Console/Commans目录下创建SwooleManger.php文件。

    <?php
    namespace App\Console\Commands;    
    use Illuminate\Console\Command;
    use Illuminate\Support\Facades\App;
    class SwooleManger extends Command
    {
        private $server;

        private $pid_file;
        /**
         * The name and signature of the console command.
         *
         * @var string
         */
        protected $signature = 'swoole {action}';

        /**
         * The console command description.
         *
         * @var string
         */
        protected $description = 'start or stop the swoole process';

        /**
         * Create a new command instance.
         *
         * @return void
         */
        public function __construct()
        {
            parent::__construct();
            $this->pid_file =  __DIR__.'/../../../storage/swoole_websocket.pid';
        }

        /**
         * Execute the console command.
         *
         * @return mixed
         */
        public function handle()
        {
            //获取传递的操作
            $arg = $this->argument('action');

            switch ($arg){
                case 'start':
                    //检测进程是否已开启
                    $pid = $this->getPid();
                    if($pid && \Swoole\Process::kill($pid,0))
                    {
                        $this->error("\r\nprocess already exist!\r\n");
                        exit;
                    }

                    $this->server = new \swoole_websocket_server("0.0.0.0", 9501);
                    $this->server->set([
                        'worker_num'=>8,
                        'daemonize' =>1,
                        'max_request'=>1000,
                        'dispatch_mode'=>2,
                        'pid_file' =>$this->pid_file,
                    ]);

                    //绑定操作类回调函数
                    $app = App::make('App\Handles\SwooleWebSocketHandle');

                    $this->server->on('open',array($app,'onOpen'));

                    $this->server->on('message',array($app,'onMessage'));

                    $this->server->on('close',array($app,'onClose'));

                    $this->info("\r\nprocess created successful!\r\n");

                    $this->server->start();
                    break;

                case 'stop':
                    if(!$pid = $this->getPid())
                    {
                        $this->error("\r\nprocess not started!\r\n");
                        exit;
                    }
                    if(\Swoole\Process::kill((int)$pid))
                    {
                        $this->info("\r\nprocess close successful!\r\n");
                        exit;
                    }
                    $this->info("\r\nprocess close failed!\r\n");
                    break;

                default:
                    $this->error("\r\noperation method does not exist!\r\n");
            }

        }

        //获取pid
        private function getPid()
        {
            return file_exists($this->pid_file) ? file_get_contents($this->pid_file) :false;
        }
    }

以上命令定义完成可使用artisan来管理swoole websocket服务的开启和关闭

php artisan swoole start  //开启
php artisan swoole stop //关闭

2.使用Handles类来处理swoole的事件处理

//在SwooleManger中使用了 
$app = App::make('App\Handles\SwooleWebSocketHandle'); //将SwooleWebsocketHandle注入到SwooleManger中

使用$this->server->on 注册事件回调函数,创建App\Handles\SwooleWebSocketHandle文件实现webSocket的事件即可

本作品采用《CC 协议》,转载必须注明作者和本文链接
死磕,不要放弃,终将会有所收获。
附言 1  ·  5年前

感谢@好好先森V5提醒,已把进程判断改为读取pid文件和 做了一些优化

本帖由系统于 5年前 自动加精
讨论数量: 7

ps -ef|grep swoole 这种方式不太严谨,这样的话一个操作系统只能起一个项目的swoole进程,不能开多组swoole进程。
记录pid到文件,管理时读取pid文件,然后发信号即可,这可能是更好的做法。

5年前 评论

我就比较粗暴shell_exec('ps -ef|grep swoole|cut -c 9-15|xargs kill -9'); :joy:

4年前 评论
Groot (楼主) 4年前

有一个问题,如果关闭的时候管道中还有数据正在处理,这样关闭会导致数据未处理完导致异常

5年前 评论

@侧面 这个没有理解过,是否可用kill -QUIT,还请赐教?

5年前 评论

@好好先森V5 嗯,你的方法很棒,在这个示例中没有考虑多组服务,存在多组也可以使用命令参数来区分吧

5年前 评论

@kite Swoole 1.9.5+ 提供了自动创建pidfile的功能,如果要兼容低版本,可以手动创建此文件,示例

不用客气,技术交流。

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!