SWOOLE 實現進程的守護


一、 進程守護使用場景。

后端經常會有類似這樣的場景,某個腳本,需要不斷的重復運行,這個時候,最好有一

個守護程序,幫助我們不斷地自動地拉起這些腳本進程,讓它自動地重復運行。

在 Linux/Unix 系統下,supervisor 就是使用 python 開發的一個優秀的進程管理工

具,本文嘗試使用 php 來實現類似的進程管理工具。

二、swoole 的進程管理模塊。

php 的 swoole 擴展有一個進程管理模塊,官方文檔見:swoole 進程管理模塊

參考 supervisor 的實現方式,被守護的進程是作為 supervisor 的子進程來啟動的,

supervisor 通過監聽子進程的信號,可實現對子進程的自動重啟等功能。而 swoole

的進程管理模塊就提供了進程間通信的功能,可以實現對子進程的自動重啟功能。

三、第一個進程守護程序。

要實現對子程序的守護,需要做到兩點:

1. 程序需要監聽到子進程的結束信號,以便於重新拉起新的子進程。

2. 子進程的運行環境需要獨立於父進程。swoole 進程管理模塊提供了一個 bool Process->exec(string $execfile, array

$args) 方法,讓子進程蛻變成另一個系統調用程序,同時還能保證父進程與當前進程

仍然是父子進程關系。

再通過 array Process::wait(bool $blocking = true) 方法,來等待子進程的退出信號。

下面是使用 swoole 啟動子進程,並回收子進程資源的示例代碼:

<?phpuse Swoole\Process;

$php = "/usr/bin/env php";

$script = dirname(__DIR__) . "/task.php";

$command = "{$php} {$script}";

$process = new Process(function (Process $worker) use ($command) {

$worker->exec('/bin/sh', ['-c', $command]);

});

$pid = $process->start();

printf("啟動子進程 {$pid}\n");

while ($ret = Process::wait()) {

$pid = intval($ret["pid"] ?? 0);

printf("子進程 {$pid} 結束\n");}

代碼解析:

$command 變量表示需要子進程腳本,通過 exec() 方法來啟動成一個子進程的方式

運行,再通過 Process::wait() 訪求來等待 $command 這個子進程腳本結束,並回收

進程資源。

那么,只要在收到子進程的結束信號后,再起一個相同的子進程腳本,即可實現對子進

程的守護了。於是,第一個守護子進程的程序實現代碼:

<?phpuse Swoole\Process;

$php = "/usr/bin/env php";

$script = dirname(__DIR__) . "/task.php";

$command = "{$php} {$script}";

do {

$process = new Process(function (Process $worker) use ($command) {

$worker->exec('/bin/sh', ['-c', $command]);

});

$pid = $process->start();

printf("啟動子進程 {$pid}\n");

} while (Process::wait());代碼解析:

這段代碼只將啟動子進程的邏輯加到一個死循環中,好讓這個子進程腳本能夠不斷的重

啟。

四、封裝成類

為了方便重用這段代碼,可以將這段代碼封裝成一個簡單的類:

<?phpnamespace App;

use Swoole\Process;

class Daemon{

/** @var string */

private $command;

public function __construct(string $command)

{

$this->command = $command;

}

public function run()

{

do {

$process = new Process(function (Process $worker) {

$worker->exec('/bin/sh', ['-c', $this->command]); });

$pid = $process->start();

} while (Process::wait());

}

}

那么,這個 Daemon 類的使用方式如下:

<?php

use App\Daemon;

$php = "/usr/bin/env php";

$script = dirname(__DIR__) . "/task.php";

$command = "{$php} {$script}";

$daemon = new Daemon($command);

$daemon->run();

這個簡單 Daemon 類雖然能實現對單個腳本進行重啟守護,但是,如果我們有許多個

腳本同時需要守護的,這個 Daemon 類顯然是不能夠滿足需求的。

有需要交流的小伙伴可以點擊這里加本人QQ:luke


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM