正文 5348字数 2,430,256阅读


一、安装 workerman
在项目根目录执行
composer require workerman/workerman
Run code
Cut to clipboard


    二、创建自定义 artisan 命令来启动 workerman 服务
    由于 laravel 不能直接在根目录下执行 php 命令,所以需要创建 artisan 命令用于后面 workerman 服务的开启。

    1,生成 WorkermanCommand 文件
    php artisan make:command WorkermanCommand
    Run code
    Cut to clipboard

      执行以上命令行会在 app/Console/Commands/ 目录下生成 WorkermanCommand.php 文件。
      <?php namespace App\Console\Commands; use Workerman\Worker; use Illuminate\Console\Command; class WorkermanCommand extends Command { private $server; /** * The name and signature of the console command. * * @var string */ protected $signature = 'wk {action}'; /** * The console command description. * * @var string */ protected $description = 'Start a Workerman server.'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { global $argv; $arg = $this->argument('action'); $argv[1] = $argv[2]; $argv[2] = isset($argv[3]) ? "-{$argv[3]}" : ''; switch ($arg) { case 'start': $this->start(); break; case 'stop': break; case 'restart': break; case 'reload': break; case 'status': break; case 'connections': break; } } private function start() { // 创建一个Worker监听20002端口,不使用任何应用层协议 $this->server = new Worker("tcp://0.0.0.0:20002"); // 启动4个进程对外提供服务 $this->server->count = 4; $handler = \App::make('handlers\WorkermanHandler'); // 连接时回调 $this->server->onConnect = [$handler, 'onConnect']; // 收到客户端信息时回调 $this->server->onMessage = [$handler, 'onMessage']; // 进程启动后的回调 $this->server->onWorkerStart = [$handler, 'onWorkerStart']; // 断开时触发的回调 $this->server->onClose = [$handler, 'onClose']; // 运行worker Worker::runAll(); } }
      Run code
      Cut to clipboard


        我只实现了 start 命令,其他命令童鞋们自行实现吧。
        这里使用了 PHP 类方法的回调。(PHP几种回调写法)
        这里我们创建了一个自定义命令 wk [action] ,通过此命令即可开启 workerman 服务。

        注册命令
        https://laravel-china.org/docs/laravel/5.4/artisan/1245#7ed55e
        命令编写完成后,需要注册 Artisan 后才能使用。注册文件为 app/Console/Kernel.php 。在这个文件中, 你会在 commands 属性中看到一个命令列表。要注册你的命令,只需将其加到该列表中即可。当 Artisan 启动时,所有罗列在这个 属性的命令,都会被 服务容器 解析并向 Artisan 注册:
        protected $commands = [ // Commands\WorkermanCommand::class ];
        Run code
        Cut to clipboard

          在这个自定义命令还引用了其他的类文件,如:
          $handler = \App::make('handlers\WorkermanHandler');
          Run code
          Cut to clipboard

            所以,需要创建一个 WorkermanHandler.php 的文件来处理对应的操作。

            2,创建 WorkermanHandler.php
            创建文件 app/handlers/WorkermanHandler.php
            <?php namespace handlers; use Workerman\Lib\Timer; // 心跳间隔10秒 define('HEARTBEAT_TIME', 10); class WorkermanHandler { // 处理客户端连接 public function onConnect($connection) { echo "new connection from ip " . $connection->getRemoteIp() . "\n"; } // 处理客户端消息 public function onMessage($connection, $data) { // 向客户端发送hello $data $connection->send('Hello, your send message is: ' . $data); } // 处理客户端断开 public function onClose($connection) { echo "connection closed from ip {$connection->getRemoteIp()}\n"; } public function onWorkerStart($worker) { Timer::add(1, function () use ($worker) { $time_now = time(); foreach ($worker->connections as $connection) { // 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间 if (empty($connection->lastMessageTime)) { $connection->lastMessageTime = $time_now; continue; } // 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接 if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) { echo "Client ip {$connection->getRemoteIp()} timeout!!!\n"; $connection->close(); } } }); } }
            Run code
            Cut to clipboard


              3,修改 composer.json 文件,让 app/handlers 文件夹下的类文件自动加载。
              "autoload": { "classmap": [ ... "app/handlers" ], ... },
              Run code
              Cut to clipboard

                运行命令类文件自动加载
                composer dump-autoload
                Run code
                Cut to clipboard

                  至此。workman的命令定义已经完成。

                  使用:
                  php artisan wk start
                  Run code
                  Cut to clipboard


                    如果看到以下内容,说明 workerman 服务启动正常:
                    Workerman[artisan] start in DEBUG mode ----------------------- WORKERMAN ----------------------------- Workerman version:3.5.4 PHP version:7.1.4 ------------------------ WORKERS ------------------------------- user worker listen processes status root none tcp://0.0.0.0:20002 1 [OK] ---------------------------------------------------------------- Press Ctrl+C to quit. Start success.
                    Run code
                    Cut to clipboard


                      https://www.jianshu.com/p/00623acb3dad