Swoole-2.1.2 進程池模塊的使用

Swoole-2.1.2版本中咱們將Server的進程管理模塊封裝成了PHP類,如今能夠在PHP代碼中使用Swoole的進程管理器了。php

在實際項目中常常須要寫一些長期運行的腳本,如基於rediskafkarabbitmq實現的多進程隊列消費者,多進程爬蟲等等。程序員須要使用pcntlposix相關的擴展庫實現多進程編程,須要開發者具有深厚的Linux系統編程功底,不然很容易出現問題。程序員

Swoole提供的進程管理器來自於Swoole\Server,通過大量生產項目驗證,穩定性和健壯性都很是高。可大大簡化多進程腳本編程工做。redis

1、 建立進程池

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

  • 某個工做進程遇到致命錯誤、主動退出時管理器會進行回收,避免出現殭屍進程
  • 工做進程退出後,管理器會自動拉起、建立一個新的工做進程

2、信號處理

Swoole進程管理器自帶了信號處理,向管理器進程發送:socket

  • SIGTERM信號:停止服務,向全部工做進程發送SIGTERM關閉進程
  • SIGUSR1信號:重啓工做進程,管理器會逐個重啓工做進程

在工做進程中能夠配合使用pcntl_signalpcntl_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);
     }
});

3、任務投遞

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

TCP 端口

$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);
相關文章
相關標籤/搜索