misterion/ko-process

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

v0.5.3 2016-04-04 14:02 UTC

This package is not auto-updated.

Last update: 2024-09-14 15:42:32 UTC


README

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

Ko-Process 允许轻松进行可调用的分叉。它是对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\SharedMemory 使用 Semaphore 进行内部锁定,因此可以安全地用于进程间通信。共享内存实现了 \ArrayAccess\Countable 接口,因此可以像数组一样访问。

$sm = new SharedMemory(5000); //allocate 5000 bytes
$sm['key1'] = 'value';

echo 'Total keys is' . count($sm) . PHP_EOL;
echo 'The key with name `key1` exists: ' . isset($sm['key1'] . PHP_EOL;
echo 'The value of key1 is ' . $sm['key1'] . PHP_EOL;

unset($sm['key1']);
echo 'The key with name `key1` after unset exists: ' . isset($sm['key1'] . PHP_EOL;

您可以使用 Semaphore 进行进程间锁定

$s = new Semaphore();
$s->acquire();
//do some job
$s->release();

//or
$s->tryExecute(function() {
    //do some job
});

致谢

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

许可证

MIT许可证下发布。

链接