anuyun/ko-process-thin

简单的 pcntl fork 包装和进程管理器

dev-master 2017-02-07 03:09 UTC

This package is not auto-updated.

Last update: 2024-09-23 15:05:16 UTC


README

Build Status Latest Stable Version Code Coverage Scrutinizer Code Quality Total Downloads Latest Unstable Version License

Ko-Process 允许轻松地调用 fork。它是对 PHP 扩展 PCNTL 中 fork 部分的面向对象包装。后台进程、将进程从控制终端分离、信号和退出代码以及通过共享内存的简单 IPC。这是一个经过良好测试的库,用于现实世界的高负载项目。

安装

需求

PHP >= 5.4
pcntl extension installed
posix extension installed

通过 Composer

安装库的推荐方法是 composer。您可以在 Packagist 上查看 包信息

{
	"require": {
		"misterion/ko-process": "*"
	}
}

不使用 composer?

只需克隆存储库,并注意 Ko 命名空间的自动加载。

用法

基本用法如下

$manager = new Ko\ProcessManager();
$process = $manager->fork(function(Ko\Process $p) {
    echo 'Hello from ' . $p->getPid();
})->onSuccess(function() {
    echo 'Success finish!';
})->wait();

如果应该等待所有已分叉的进程

$manager = new Ko\ProcessManager();
for ($i = 0; $i < 10; $i++) {
    $manager->fork(function(Ko\Process $p) {
        echo 'Hello from ' . $p->getPid();
        sleep(1);
    });
}
$manager->wait();

进程标题?

是的,ProcessManagerProcess 都可以使用 setProcessTitle 函数更改进程标题。或者,您也可以使用 trait Ko\Mixin\ProcessTitle 将此功能添加到任何您想要的类中。请注意 ProcessManager::onShutdown - 如果 ProcessManager 捕获 SIGTERM,则会调用可调用的函数。处理程序会在子进程关闭之前被调用。我们使用 demonize 来从终端分离。使用以下代码运行示例

$manager = new Ko\ProcessManager();
$manager->demonize();
$manager->setProcessTitle('I_am_a_master!');
$manager->onShutdown(function() use ($manager) {
    echo 'Catch sigterm.Quiting...' . PHP_EOL;
    exit();
});

echo 'Execute `kill ' . getmypid() . '` from console to stop script' . PHP_EOL;
while(true) {
    $manager->dispatch();
    sleep(1);
}

ps aux|grep I_am_a_mastertop 来查看您的进程标题在 Linux 进程列表中。

孵化

在创建主 - 子进程模式的程序时,您应该注意子进程是否存活。`spawn` 函数将帮助您实现这一点 - 一旦 `spawn` 会保持分叉进程在退出时带有某些错误代码的情况下存活。

$manager = new Ko\ProcessManager();
for ($i = 0; $i < 10; $i++) {
    $manager->spawn(function(Ko\Process $p) {
        echo 'Hello from ' . $p->getPid();
        sleep(1);
        exit(1); //exit with non 0 exit code
    });
}
$manager->wait(); //we have auto respawn for 10 forks

让我们假设您正在基于 PhpAmqpLib\AMPQ 的队列工作者上编写一些内容。因此,您可以编写如下内容

use PhpAmqpLib\Connection\AMQPConnection;
use PhpAmqpLib\Message\AMQPMessage;

$manager = new Ko\ProcessManager();
$manager->setProcessTitle('Master:working...');
$manager->spawn(function(Ko\Process $p) {
    $connection = new AMQPConnection('localhost', 5672, 'guest', 'guest');
    $channel = $connection->channel();

    $channel->queue_declare('hello', false, true, false, false);

    $callback = function($msg) use (&$p) {
        $p->setProcessTitle('Worker:processJob ' . $msg->body);

        //will execute our job in separate process
        $m = new Ko\ProcessManager();
        $m->fork(function(Ko\Process $jobProcess) use ($msg) {
            $jobProcess->setProcessTitle('Job:processing ' . $msg->body);

            echo " [x] Received ", $msg->body, "\n";
            sleep(2);
            echo " [x] Done", "\n";
        })->onSuccess(function() use ($msg){
            //Ack on success
            $msg->delivery_info['channel']
                ->basic_ack($msg->delivery_info['delivery_tag']);
        })->wait();

        $p->setProcessTitle('Worker:waiting for job... ');

        //IMPORTANT! You should call dispatch() them self to process pending signals.
        $p->dispatch();

        if ($p->isShouldShutdown()) {
            exit();
        }
    };

    $channel->basic_qos(null, 1, null);
    $channel->basic_consume('hello', '', false, false, false, false, $callback);

    while(count($channel->callbacks)) {
        $channel->wait();
    }

    $channel->close();
    $connection->close();
});
$manager->wait();

致谢

Ko-process 是由 Nikolay Bondarenko (misterionkell at gmail.com) 作为 GameNet 项目 的一部分编写的。

许可

MIT 许可下发布。

链接