ThinkPHP 5.1 Workerman 快速上手指南

本篇内容主要讲述了最新的think-worker扩展的使用。

  • 安装Workermanthink-worker

  • 启动Workerman HTTP服务

  • 守护进程模式

  • 基本操作(只支持Linux环境)

  • 配置文件

  • 修改地址和端口

  • 文件监控

  • 事件回调

  • 静态资源访问

  • HTTPS支持

  • 其它注意事项

  • Windows版本问题

  • 快速启动Workerman Server

  • 守护进程

  • 配置文件

  • 自定义服务类

  • 启动多个Workerman服务

  • GatewayWorker支持

  • 安装GatewayWorker

  • 守护进程模式

  • 配置文件

  • 分布式部署

本指南的目的不是为了让你掌握Workerman开发,而且帮助你使用think-worker快速部署ThinkPHP5.1应用到WorkermanHttpServer,以及使用快速启动Workerman服务(包括GatewayWorker),如果你需要了解Workerman的具体用法和原理,请参考Workerman官方文档,说的比较详细了。

本文的内容并不适用于ThinkPHP 5.0及以下版本 !如果你发现文中的例子没法正确执行,请检查你的think-worker扩展是否已经更新到最新版本。

安装Workermanthink-worker

Workerman是一款纯PHP开发的开源高性能的PHP socket 服务器框架。而 think-worker则是ThinkPHP官方发布的一个workerman扩展,从2.0+版本完善了对Workerman的支持。

Workerman是一个纯PHP的实现,因此基本上不需要特殊的安装,你只需要通过composer直接安装即可。

composer require workerman/workerman

注意,最新版本的workerman已经统一了Linux和Windows版本,因此不需要单独安装windows版本了。

事实上在安装think-worker扩展的时候会自动安装workerman依赖包,所以直接在你的项目根目录下运行下面的命令安装扩展,如果你还没有安装workerman的话也会自动安装。

composer require topthink/think-worker

本文中的内容以最新版本的扩展为例(最好确保安装的是V2.0.8+版本,可能部分功能老版本的扩展不支持),如果你的扩展版本较旧,请更新框架或者扩展版本。

ThinkPHP5+的扩展都是基于Composer安装的,所以确认你已经安装了Composer

如果你已经有自己的ThinkPHP5.1项目了,为了支持最新的特性,建议更新到最新版本V5.1.20+),然后可以在应用根目录下使用下面命令安装扩展。

composer require topthink/think-worker

会安装最新的稳定版本的think-worker扩展。

如果你是第一次使用ThinkPHP5.1,那么可以先创建一个初始项目,然后再安装扩展,依次执行下面的命令即可。

composer create-project topthink/think tp
cd tp
composer require topthink/think-worker

启动Workerman HTTP服务

第一个场景(也是该扩展最重要的一个场景),毕竟大部分使用think-worker扩展的用户都是在使用ThinkPHP开发网站或者项目,使用think-worker扩展可以让你的产品直接部署到Workerman上,并且享受下面的优势:

  • 无需对代码进行改造就能带来性能的数倍提升;
  • 可以在Apache/Nginx等传统WEB服务器和Workerman之间切换部署;

简单点说,就是你可以在传统模式下开发你的应用,然后直接部署到Workerman上运行,但无需针对Workerman写任何的处理代码。

安装完扩展后,你什么都不需要做,最简单的就是直接在命令行(应用根目录下面)下执行:

php think worker

启动成功后会显示类似下面的信息

Starting Workerman http server...
Workerman[think] start in DEBUG mode
----------------------- WORKERMAN -----------------------------
Workerman version:3.5.13          PHP version:7.2.7-0ubuntu0.18.04.2
------------------------ WORKERS -------------------------------
user          worker        listen               processes status
kancloud      thinkphp      http://0.0.0.0:2346   4         [OK]
----------------------------------------------------------------
Press Ctrl+C to stop. Start success.

可以看到已经在0.0.0.0:2346启动一个HTTP Server服务端(默认启动的是调试模式),下面我们可以直接访问当前的应用。

http://localhost:2346

如果你之前已经有运行一个80端口的WEB服务,可以同时访问,你也可以比较下两个页面的区别。

如果你是刚创建的项目,那么可以直接看到ThinkPHP5.1的欢迎页面。

[图片上传失败...(image-d396aa-1565236395761)]

否则你会看到你的项目首页。

守护进程模式

如果需要使用守护进程模式运行(只支持Linux环境),可以使用

php think worker -d

会看到类似下面的信息:

Starting Workerman http server...
----------------------- WORKERMAN -----------------------------
Workerman version:3.5.13          PHP version:7.2.7-0ubuntu0.18.04.2
------------------------ WORKERS -------------------------------
user          worker        listen               processes status
kancloud      thinkphp      http://0.0.0.0:2346   4         [OK]
----------------------------------------------------------------
Input "php think stop" to stop. Start success.

注意,最后一句php think stop提示信息并不正确,这是由于Workerman没有准确定位到入口文件导致。stop命令的正确用法,我们会在后面讲到。

基本操作(只支持Linux环境)

这一节的内容只支持Linux环境

可以在命令行使用

php think worker [操作]

如果没有输入任何操作,则默认为start操作。

支持的操作包括:

操作 描述
start 启动服务(默认操作)
reload 平滑重启
stop 停止服务
restart 重启服务
status 查看服务运行信息
connections 查看连接信息

如果要停止服务,可以使用

php think worker stop

reload服务

php think worker reload

stop服务

php think worker stop

restart服务

php think worker restart

restartreload的区别是,restart会先stop然后start,而reload则是平滑重启服务,不会中断服务。

配置文件

HTTPServer的参数可以在应用配置目录下的worker.php里面配置,该文件会在扩展安装的时候自动生成(如果没有则可以自己创建)。

扩展自带的配置参数主要包括:

配置参数 描述 默认值
host 监听地址 0.0.0.0
port 监听端口 2346
root WEB根目录 public目录
app_path 应用目录(守护进程模式必须设置) 自动识别
file_monitor 是否监控文件更改(V2.0.9+) false
file_monitor_interval 监控文件间隔(秒)(V2.0.9+) 2
file_monitor_path 监控目录 (V2.0.9+) 默认监控application和config目录

其它的workerman参数可以参考官方文档的Worker类属性,所有Workerman本身支持的配置参数都可以直接在worker.php中使用。

修改地址和端口

如果你需要修改地址和端口,可以修改worker.php配置文件

'host'     => 'tp5.com', // 监听地址
'port'     => 8080, // 监听端口

改完后,需要重启服务才能生效

php think worker restart

如果是在windows下面的话,可以使用CTRL+C停止服务,然后再启动服务。

现在可以直接访问

http://tp5.com:8080

如果你需要设置80端口,需要root权限才可以。

如果你安装的是2.0.8+版本的扩展,还可以支持在命令行指定地址和端口,例如:

php think worker -H tp.com -p 2800

会显示如下信息:

Starting Workerman http server...
Workerman[think] start in DEBUG mode
----------------------- WORKERMAN -----------------------------
Workerman version:3.5.13          PHP version:7.2.7-0ubuntu0.18.04.2
------------------------ WORKERS -------------------------------
user          worker        listen              processes status
kancloud      thinkphp      http://tp.com:2800   4         [OK]
----------------------------------------------------------------
Press Ctrl+C to stop. Start success.

如果配置文件和命令行都指定了hostport选项,则命令行参数优先。

如果启动了多个不同端口的服务,reloadrestartstop等操作必须也是针对某个端口的才能正确操作,我们以reload操作为例进行说明。

如果我们需要reload前面启动的tp.com:2800服务,下面的指令是错误的

php think worker reload

可能会出现错误提示:

Workerman[think] reload
Workerman[think] not run

必须带上正确的端口号(host不是必须的)

php think worker reload  -p 2800

然后,你会看到提示信息如下,表示reload成功:

Workerman[think] reload

文件监控

由于Workerman服务运行过程中PHP文件是常驻内存运行的,这样可以避免重复读取磁盘、重复解释编译PHP,以便达到最高性能。所以更改业务代码后必须手动reload或者restart才能生效。

think-worker扩展提供了监控文件更新的功能,在检测到相关目录的文件有更新后会自动reload,从而不需要手动进行reload操作,方便开发调试。

如果你的应用开启了调试模式,文件监控功能是自动开启的,为了便于调试,我们强烈建议在开发阶段开启调试模式。

原则上,在部署模式下不建议开启文件监控,一方面有性能损耗,另外一方面对文件所做的任何修改都需要确认无误才能进行更新部署。另外由于windows下不支持reload操作,因此文件监控功能只支持Linux环境。

如果你确实需要在部署模式下开启文件监控,可以设置如下:

'file_monitor'  =>  true, // 开启文件监控
'file_monitor_interval' =>  1, // 文件监控检测的时间间隔
'file_monitor_path' =>  '', // 文件监控目录 一般不需要设置 默认会监控应用目录和配置目录

在调试模式下,或者开启了文件监控后,我们进行一下测试。

修改你的Index控制器文件,在index方法中添加一段调试输出代码

dump('hello');

然后刷新你的浏览器访问,看是否已经实时生效了。

文件监控的目录默认会自动监控应用目录application和配置文件目录config下面的php文件,如果你还需要增加其它的监控目录,例如增加路由配置目录,可以设置为:

'file_monitor_path' =>  [
    '/home/www/tp.com/application',
    '/home/www/tp.com/config',
    '/home/www/tp.com/route',
]

或者设置整个项目目录进行文件监控

'file_monitor_path' =>  [
    '/home/www/tp.com'
]

事件回调

扩展自带的HTTPServer包含了onWorkerStartonMessage两个事件回调,你如果需要增加其它的回调事件处理,可以在配置文件中直接添加:

'onConnect' => function($connection)
{
    echo "new connection from ip " . $connection->getRemoteIp() . "\n";
},
'onClose'   => function($connection)
{
    echo "connection closed\n";
},

关于事件回调的具体用法,可以参考workerman官方文档的回调属性。

如果不熟悉内部机制,请勿随意替换和更改onWorkerStartonMessage事件回调,会导致不可预期的结果。

静态资源访问

为了确保静态资源的正常访问,请确认下面的参数配置正确:

// 网站根目录位置
'root'         => Env::get('root_path') . 'public',

使用Chrome浏览器会自动请求一次favicon.ico,所以确保你的网站根目录下面有存在favicon.ico文件,否则会产生一次404请求的错误日志。

HTTPS支持

Workerman开启SSL的前提如下:

  • Workerman版本不小于3.3.7
  • PHP安装了openssl扩展
  • 已经申请了证书(pem/crt文件及key文件,假设放在了/etc/nginx/conf.d/ssl下)

然后在worker.php配置文件中设置

'host'  =>  '0.0.0.0',
'port'  =>  443,

// 开启SSL访问支持
'ssl'   =>  true,
// 或者改为下面的配置
// 'transport'  =>  'ssl',

'context' => [
    'ssl' => [
        'local_cert'  => '/etc/nginx/conf.d/ssl/server.pem', // 也可以是crt文件
        'local_pk'    => '/etc/nginx/conf.d/ssl/server.key',
        'verify_peer' => false,
    ],
],

现在客户端就可以通过https协议来连接了。

注意:

  • https端口必须用https协议访问,http协议无法访问。
  • 证书一般是与域名绑定的,所以测试的时候请使用域名访问,不要使用ip。
  • 如果使用https无法访问请检查服务器防火墙。

也利用nginx作为ssl的代理,具体配置可以参考官方手册说明。

其它注意事项

Workerman下面,不建议直接使用$_GET$_POST$_REQUEST$_SERVER$_COOKIE以及$_SESSION等原生的PHP用法,推荐使用框架提供的类和方法进行获取。

由于onWorkerStart运行的时候还没有HTTP_HOST,因此最好在应用配置文件config/app.php中设置app_host

请不要调用PHP原生的header方法,使用Response对象的header方法替代。
不要使用PHP原生的session相关函数,使用Session类的相关方法。

Windows版本问题

WorkermanWindows版本与Linux的主要区别包括:

  • win版本count属性无效,全部为单进程
  • 不支持start之外的操作命令(可以用CTRL+C停止运行)
  • cmd命令行启动,后面可接多个文件,例如 php start_web.php start_gateway.php start_worker.php
  • 无法守护进程,cmd窗口关掉后服务即停止

快速启动Workerman Server

现在来看第二个场景,通过简单的配置快速启动一个Workerman服务,包括WebSocket/Http/Socket服务。

可以支持直接启动一个Workerman server(需要think-worker扩展 2.0.7+版本)

php think worker:server

会显示如下信息:

Starting Workerman server...
Workerman[think] start in DEBUG mode
----------------------- WORKERMAN -----------------------------
Workerman version:3.5.13          PHP version:7.2.7-0ubuntu0.18.04.2
------------------------ WORKERS -------------------------------
user          worker        listen                    processes status
kancloud      thinkphp      websocket://0.0.0.0:2345   4         [OK]
----------------------------------------------------------------
Press Ctrl+C to stop. Start success.

这个时候已经在0.0.0.0:2345启动一个Websocket服务。

你可以在浏览器中访问

http://127.0.0.1:2345

会看到如下信息:

400 Bad Request
Sec-WebSocket-Key not found.
This is a WebSocket service and can not be accessed via HTTP.
See http://wiki.workerman.net/Error1 for detail.

这是因为Workerman的WebSocket协议不支持通过HTTP访问,可以通过JS代码测试。

ws = new WebSocket("ws://127.0.0.1:2345");
ws.onopen = function() {
    alert("连接成功");
    ws.send('hello,thinkphp');
    alert("给服务端发送一个字符串:hello,thinkphp");
};
ws.onmessage = function(e) {
    alert("收到服务端的消息:" + e.data);
};

守护进程

如果需要使用守护进程方式运行,可以使用

php think worker:server -d

配置文件

如果需要自定义参数,可以在config/worker_server.php中进行配置,包括:

配置参数 描述 默认值
protocol 协议 websocket
host 监听地址 0.0.0.0
port 监听端口 2345
socket 完整socket地址
context socket 上下文选项
daemonize 守护进程 false

注意不要和worker.php文件文件混淆,两者的作用完全不同。

并且支持Workerman所有的参数,以及支持使用闭包方式定义相关事件回调。

return [
    // 扩展自身需要的配置
    'protocol'       => 'websocket', // 协议 支持 tcp udp unix http websocket text
    'host'           => '0.0.0.0', // 监听地址
    'port'           => 2345, // 监听端口

    // 支持workerman的所有配置参数
    'name'           => 'thinkphp',
    'count'          => 4,
    'daemonize'      => false,
    'pidFile'        => Env::get('runtime_path') . 'worker.pid',

    // 支持事件回调
    // onWorkerStart
    'onWorkerStart'  => function ($worker) {

    },
    // onWorkerReload
    'onWorkerReload' => function ($worker) {

    },
    // onConnect
    'onConnect'      => function ($connection) {

    },
    // onMessage
    'onMessage'      => function ($connection, $data) {
        $connection->send('receive success');
    },
    // onClose
    'onClose'        => function ($connection) {

    },
    // onError
    'onError'        => function ($connection, $code, $msg) {
        echo "error [ $code ] $msg\n";
    },
];

自定义服务类

如果你需要更高级的自定义事件回调,也可以使用自定义的Worker服务类。

 4,
        'pidFile'   => Env::get('runtime_path') . 'worker.pid',
        'name'      => 'think'
    ];

    public function onMessage($connection, $data)
    {
        $connection->send('receive success');
    }
}

自定义服务类必须继承think\worker\Server类,支持workerman所有的回调方法定义(回调方法必须是public类型)。

然后在worker_server.php中增加配置参数:

return [
    'worker_class'  =>  'app\http\Worker',
];

定义该参数后,其它配置参数均不再有效。

然后就可以在命令行启动服务端

php think worker:server

一样可以支持使用守护进程模式运行,

php think worker:server -d

同样也支持reloadrestartstop 操作。

php think worker:server reload

启动多个Workerman服务

你可以通过命令行的指令启动多个不同端口的workerman服务,例如:

php think worker:server -p 2800
php think worker:server -p 2801

如果要分别对不同端口的服务进行stop操作,务必使用

php think worker:server stop -p 2800
php think worker:server stop -p 2801

如果你自定义了服务入口类,那么可以定义多个入口类

 4,
        'pidFile'   => Env::get('runtime_path') . 'worker1.pid',
        'name'      => 'think'
    ];

    public function onMessage($connection, $data)
    {
        $connection->send('receive success');
    }
}

 4,
        'pidFile'   => Env::get('runtime_path') . 'worker2.pid',
        'name'      => 'think'
    ];

    public function onMessage($connection, $data)
    {
        $connection->send('receive success');
    }
}

然后在worker_server.php中增加配置参数:

return [
    'worker_class'  =>  ['app\http\Worker1', 'app\http\Worker2'],
];

运行启动指令后可以看到启动了两个不同的服务

php think worker:server 

GatewayWorker支持

V2.0.8+版本开始,think-worker扩展可以支持GatewayWorker

GatewayWorker是基于Workerman开发的一套TCP长连接的应用框架,实现了单发、群发、广播等接口,内置了mysql类库,GatewayWorker分为Gateway进程和Worker进程,天然支持分布式部署。

安装GatewayWorker

首先确保你已经安装了GatewayWorker,如果还没有,可以使用下面的命令安装

composer require workerman/gateway-worker

接下来,可以直接在命令行运行

php think worker:gateway

会显示下面的信息,表示启动成功。

Starting GatewayWorker server...
Workerman[think] start in DEBUG mode
----------------------- WORKERMAN -----------------------------
Workerman version:3.5.13          PHP version:7.2.7-0ubuntu0.18.04.2
------------------------ WORKERS -------------------------------
user          worker          listen                    processes status
kancloud      Register        text://127.0.0.1:1236      1         [OK]
kancloud      BusinessWorker  none                       1         [OK]
kancloud      thinkphp        websocket://0.0.0.0:2348   1         [OK]
----------------------------------------------------------------
Press Ctrl+C to stop. Start success.

守护进程模式

如果需要使用守护进程模式,可以使用

php think worker:gateway -d

同样支持在命令行指定地址和端口

php think worker:gateway -H tp.com -p 2800

显示信息

Starting GatewayWorker server...
Workerman[think] start in DEBUG mode
----------------------- WORKERMAN -----------------------------
Workerman version:3.5.13          PHP version:7.2.7-0ubuntu0.18.04.2
------------------------ WORKERS -------------------------------
user          worker          listen                   processes status
kancloud      Register        text://127.0.0.1:1236     1         [OK]
kancloud      BusinessWorker  none                      1         [OK]
kancloud      thinkphp        websocket://tp.com:2800   1         [OK]
----------------------------------------------------------------
Press Ctrl+C to stop. Start success.

配置文件

如果需要调整配置,可以修改配置目录下面的gateway_worker.php文件,内容如下:

return [
    // 扩展自身需要的配置
    'protocol'              => 'websocket', // 协议 支持 tcp udp unix http websocket text
    'host'                  => '0.0.0.0', // 监听地址
    'port'                  => 2348, // 监听端口
    'socket'                => '', // 完整监听地址
    'context'               => [], // socket 上下文选项
    'register_deploy'       => true, // 是否需要部署register
    'businessWorker_deploy' => true, // 是否需要部署businessWorker
    'gateway_deploy'        => true, // 是否需要部署gateway

    // Register配置
    'registerAddress'       => '127.0.0.1:1236',

    // Gateway配置
    'name'                  => 'thinkphp',
    'count'                 => 1,
    'lanIp'                 => '127.0.0.1',
    'startPort'             => 2000,
    'daemonize'             => false,
    'pingInterval'          => 30,
    'pingNotResponseLimit'  => 0,
    'pingData'              => '{"type":"ping"}',

    // BusinsessWorker配置
    'BusinessWorker'        => [
        'name'         => 'BusinessWorker',
        'count'        => 1,
        'eventHandler' => '\think\worker\Events',
    ],

];

默认配置参数如果需要更改,可以直接修改。

GatewayWorker开发过程中首先要配置BusinessWorker下面的eventHandler参数。系统默认提供了一个think\worker\Events类作为参考,实际请根据需要进行调整。详细用法请参考GatewayWorker手册。

分布式部署

GatewayWorker支持分布式部署,假如需要部署三台服务器(192.168.1.1-3)提供高可用服务,可以按照下面的方法进行配置操作。

第一台服务器运行统一的Register服务(该服务器同时也运行Gateway进程和BusinessWorker进程),其它两台则只部署Gateway服务和BusinessWorker服务,三台服务器的gateway_worker.php配置文件分别修改为:

192.168.1.1 gateway_worker.php

    // 分布式部署配置
    'protocol'              => 'websocket', 
    'host'                  => '0.0.0.0', // 监听地址
    'port'                  => 2348, // 监听端口
    'register_deploy'       => true, // 部署register
    'businessWorker_deploy' => true, // 部署businessWorker
    'gateway_deploy'        => true, // 部署gateway

    // Register配置
    'registerAddress'       => '192.168.1.1:1236',

    // Gateway配置
    'name'                  => 'thinkphp',
    'count'                 => 1,
    'lanIp'                 => '192.168.1.1',
    'startPort'             => 2000,
    'daemonize'             => false,
    'pingInterval'          => 30,
    'pingNotResponseLimit'  => 0,
    'pingData'              => '{"type":"ping"}',

    // BusinsessWorker配置
    'BusinessWorker'        => [
        'name'         => 'BusinessWorker',
        'count'        => 1,
        'eventHandler' => '\think\worker\Events',
    ],    

192.168.1.2 gateway_worker.php

    // 分布式部署配置
    'protocol'              => 'websocket', 
    'host'                  => '0.0.0.0', // 监听地址
    'port'                  => 2348, // 监听端口
    'register_deploy'       => false, // 不部署register
    'businessWorker_deploy' => true, // 部署businessWorker
    'gateway_deploy'        => true, // 部署gateway

    // Register配置
    'registerAddress'       => '192.168.1.1:1236',

    // Gateway配置
    'name'                  => 'thinkphp',
    'count'                 => 1,
    'lanIp'                 => '192.168.1.2',
    'startPort'             => 2000,
    'daemonize'             => false,
    'pingInterval'          => 30,
    'pingNotResponseLimit'  => 0,
    'pingData'              => '{"type":"ping"}',

    // BusinsessWorker配置
    'BusinessWorker'        => [
        'name'         => 'BusinessWorker',
        'count'        => 1,
        'eventHandler' => '\think\worker\Events',
    ],    

192.168.1.3 gateway_worker.php

    // 分布式部署配置
    'protocol'              => 'websocket', 
    'host'                  => '0.0.0.0', // 监听地址
    'port'                  => 2348, // 监听端口
    'register_deploy'       => false, // 不部署register
    'businessWorker_deploy' => true, // 部署businessWorker
    'gateway_deploy'        => true, // 部署gateway

    // Register配置
    'registerAddress'       => '192.168.1.1:1236',

    // Gateway配置
    'name'                  => 'thinkphp',
    'count'                 => 1,
    'lanIp'                 => '192.168.1.3',
    'startPort'             => 2000,
    'daemonize'             => false,
    'pingInterval'          => 30,
    'pingNotResponseLimit'  => 0,
    'pingData'              => '{"type":"ping"}',

    // BusinsessWorker配置
    'BusinessWorker'        => [
        'name'         => 'BusinessWorker',
        'count'        => 1,
        'eventHandler' => '\think\worker\Events',
    ],    

如果你需要把GatewayBusinessWorker服务分开部署,则单独设置开启或者关闭gateway_deploybusinessWorker_deploy配置参数即可。

配置调整完成后,按顺序分别启动服务,分布式部署完毕。

注意事项及说明:

1、多机部署时以下端口注意不要被服务器防火墙屏蔽(不知道服务器防火墙如何配置的请自行搜索资料学习):

①、Register服务监听的端口要可以被其它内网服务器访问(外网访问可以屏蔽);

②、如果startPort=2300; count=4;,则2300 2301 2302 2303四个端口需要被设置成能被其它服务器访问。

2、如果多机部署服务器不在一个局域网,部署时ip参数可以使用外网ip,对应端口防火墙应该设置成能被外网服务器访问。

3、三台GatewayWorker机器都运行了Gateway进程和Worker进程,客户端连接上任意一台GatewayWorkerGateway端口即通讯,开发。

4、为了方便前端接入和扩容,可以在Gateway前加一层DNS、LVS等负载均衡策略(不熟悉DNS LVS的请自行搜索资料学习)。

5、如果服务器不够用可以使用同样的方法增加服务器

6、如果需要下线服务器,直接stop对应服务器即可。由于Gateway进程维护着客户端连接,当服务器下线时,对应服务器的客户端会掉线一次。

ThinkPHP 5.1 Workerman 快速上手指南_第1张图片
code.png

你可能感兴趣的:(ThinkPHP 5.1 Workerman 快速上手指南)