在Swoole-2.1.2
版本中咱们将Server
的进程管理模块封装成了PHP
类,如今能够在PHP
代码中使用Swoole
的进程管理器了。php
在实际项目中常常须要写一些长期运行的脚本,如基于redis
、kafka
、rabbitmq
实现的多进程队列消费者,多进程爬虫等等。程序员须要使用pcntl
和posix
相关的扩展库实现多进程编程,须要开发者具有深厚的Linux
系统编程功底,不然很容易出现问题。程序员
Swoole
提供的进程管理器来自于Swoole\Server
,通过大量生产项目验证,稳定性和健壮性都很是高。可大大简化多进程脚本编程工做。redis
在PHP
代码中使用new Swoole\Process\Pool
便可建立一个进程池,构造方法的第一个参数传入工做进程的数量。使用on
方法设置WorkerStart
便可在工做进程启动时执行指定的代码,能够在这里进行while(true)
循环从redis
队列中获取任务并处理。使用start
方法启动全部进程,管理器开始进入wait
状态。编程
$workerNum = 10; $pool = new Swoole\Process\Pool($workerNum); $pool->on("WorkerStart", function ($pool, $workerId) { echo "Worker#{$workerId} is started\n"; $redis = new Redis(); $redis->pconnect('127.0.0.1', 6379); $key = "key1"; while (true) { $msgs = $redis->brpop($key, 2); if ( $msgs == null) continue; var_dump($msgs); } }); $pool->on("WorkerStop", function ($pool, $workerId) { echo "Worker#{$workerId} is stopped\n"; }); $pool->start();
使用进程管理器,能够保证工做进程的稳定性。json
Swoole
进程管理器自带了信号处理,向管理器进程发送:socket
SIGTERM
信号:停止服务,向全部工做进程发送SIGTERM
关闭进程SIGUSR1
信号:重启工做进程,管理器会逐个重启工做进程在工做进程中能够配合使用pcntl_signal
和pcntl_signal_dispatch
实现信号处理。tcp
$pool->on("WorkerStart", function ($pool, $workerId) { $running = true; pcntl_signal(SIGTERM, function () use (&$running) { $running = false; }); echo "Worker#{$workerId} is started\n"; $redis = new Redis(); $redis->pconnect('127.0.0.1', 6379); $key = "key1"; while ($running) { $msgs = $redis->brpop($key, 2); pcntl_signal_dispatch(); if ( $msgs == null) continue; var_dump($msgs); } });
Swoole
进程管理器自带了消息队列和TCP-Socket
消息投递的支持。可设置监听系统队列或者TCP
端口,接收任务数据。此项功能是可选的,要使用任务投递功能,须要对进程池对象设置onMessage
回调。ui
$pool = new Swoole\Process\Pool(2, SWOOLE_IPC_MSGQUEUE, 0x7000001); $pool->on("WorkerStart", function ($pool, $workerId) { echo "Worker#{$workerId} is started\n"; }); $pool->on("Message", function ($pool, $message) { echo "Message: {$message}\n"; }); $pool->start();
须要在构造方法的第二个参数传入SWOOLE_IPC_MSGQUEUE
,第三个参数设置监听的消息队列KEY
。其余程序中使用消息队列相关API
就能够向工做进程投递任务了。spa
$pool = new Swoole\Process\Pool(2, SWOOLE_IPC_SOCKET); $pool->on("WorkerStart", function ($pool, $workerId) { echo "Worker#{$workerId} is started\n"; }); $pool->on("Message", function ($pool, $message) { echo "Message: {$message}\n"; }); $pool->listen('127.0.0.1', 8089); $pool->start();
使用TCP
端口监听,须要设置构造方法的第二个参数为SWOOLE_IPC_SOCKET
,并使用listen
方法设置监听的主机和端口。code
底层使用了4
字节长度+包体的协议。其余程序中向此端口发送数据时,须要在数据包以前增长一个长度字段。
$fp = stream_socket_client("tcp://127.0.0.1:8089", $errno, $errstr) or die("error: $errstr\n"); $msg = json_encode(['data' => 'hello', 'uid' => 1991]); fwrite($fp, pack('N', strlen($msg)).$msg); fclose($fp);