安装Workerman和think-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上,并且享受下面的优势:
简单点说,就是你可以在传统模式下开发你的应用,然后直接部署到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的欢迎页面。
否则你会看到你的项目首页。
守护进程模式
如果需要使用守护进程模式运行(只支持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
restart和reload的区别是,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.
如果配置文件和命令行都指定了host和port选项,则命令行参数优先。
如果启动了多个不同端口的服务,reload、restart和stop等操作必须也是针对某个端口的才能正确操作,我们以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包含了onWorkerStart和onMessage两个事件回调,你如果需要增加其它的回调事件处理,可以在配置文件中直接添加:
'onConnect' => function($connection) { echo "new connection from ip " . $connection->getRemoteIp() . "\n"; }, 'onClose' => function($connection) { echo "connection closed\n"; },
关于事件回调的具体用法,可以参考workerman官方文档的回调属性。
如果不熟悉内部机制,请勿随意替换和更改onWorkerStart和onMessage事件回调,会导致不可预期的结果。
静态资源访问
为了确保静态资源的正常访问,请确认下面的参数配置正确:
// 网站根目录位置 'root' => Env::get('root_path') . 'public',
使用Chrome浏览器会自动请求一次favicon.ico,所以确保你的网站根目录下面有存在favicon.ico文件,否则会产生一次404请求的错误日志。
HTTPS支持
Workerman开启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协议来连接了。
注意:
也利用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版本问题
Workerman的Windows版本与Linux的主要区别包括:
快速启动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
同样也支持reload、restart和stop 操作。
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', ],
如果你需要把Gateway和BusinessWorker服务分开部署,则单独设置开启或者关闭gateway_deploy和businessWorker_deploy配置参数即可。
配置调整完成后,按顺序分别启动服务,分布式部署完毕。
注意事项及说明:
1、多机部署时以下端口注意不要被服务器防火墙屏蔽(不知道服务器防火墙如何配置的请自行搜索资料学习):
①、Register服务监听的端口要可以被其它内网服务器访问(外网访问可以屏蔽);
②、如果startPort=2300; count=4;,则2300 2301 2302 2303四个端口需要被设置成能被其它服务器访问。
2、如果多机部署服务器不在一个局域网,部署时ip参数可以使用外网ip,对应端口防火墙应该设置成能被外网服务器访问。
3、三台GatewayWorker机器都运行了Gateway进程和Worker进程,客户端连接上任意一台GatewayWorker的Gateway端口即通讯,开发。
4、为了方便前端接入和扩容,可以在Gateway前加一层DNS、LVS等负载均衡策略(不熟悉DNS LVS的请自行搜索资料学习)。
5、如果服务器不够用可以使用同样的方法增加服务器
6、如果需要下线服务器,直接stop对应服务器即可。由于Gateway进程维护着客户端连接,当服务器下线时,对应服务器的客户端会掉线一次。
如果您觉得文章对您有用,请点击一下下面链接支持一下吧!