zwilias/qman

基于事件的beanstalkd队列管理器

0.1.4 2016-01-27 10:19 UTC

This package is not auto-updated.

Last update: 2024-09-14 17:42:57 UTC


README

基于事件的beanstalkd队列管理器。

Build Status Scrutinizer Code Quality Code Coverage Latest Stable Version Total Downloads SensioLabsInsight

核心功能

  • 合理的默认设置,高度可扩展和可配置
  • 允许轻松地从连接池中保留
  • 支持在接收信号后优雅地关闭
  • 保护作业执行免受意外入侵
  • 可扩展的作业失败处理
  • 内置对PSR-3日志的精细粒度支持
  • 内置对队列闭包的支持

要求

  • PHP 5.5, PHP 5.6. ev 目前不支持PHP 7。
  • pcntl扩展。
  • ev,libev的接口,高性能的全功能事件循环。
  • 一个或多个beanstalkd实例。

用例

QMan针对多个beanstalkd实例以及监听所有这些实例的工作池进行了优化。

HTML View on Gliffy

示例

队列闭包

队列闭包可能是最简单的事情

use QMan\QMan;

$qMan = QMan::create(['localhost:11300']);
$qMan->queueClosure(function () {
    echo 'Hello world!';
});

本质上,这相当于以下内容

use QMan\QMan;
use QMan\ClosureCommand;

$qMan = QMan::create(['localhost:11300']);
$qMan->queue(ClosureCommand::create(function () {
    echo 'Hello world!';
}));

处理队列

使用默认参数启动工作器很简单

use Beanie\Beanie;
use QMan\WorkerBuilder;

$beanie = Beanie::pool(['localhost:11300']);
$worker = (new WorkerBuilder())
    ->build($beanie);
    
$worker->run();

WorkerBuilder 确保使用所有必需的依赖和配置设置 QMan\Worker

队列自定义命令

ClosureCommand 虽然方便,但有两个主要缺点

  • 序列化闭包在计算能力上相当昂贵
  • 单元测试闭包很快就会变成一大堆混乱

因此,你将经常需要编写自定义命令。

命令应实现 QMan\CommandInterface,这可以通过扩展 QMan\AbstractCommand 轻松完成

use QMan\AbstractCommand;

class CustomCommand extends AbstractCommand
{
    public function getType()
    {
        return 'my.custom.command';
    }
    
    public function execute()
    {
        echo $this->getData() * 5;
        return true;
    }
}

getType() 函数应返回一个字符串,该字符串可以唯一映射到要执行的类。这种间接性是必要的,以便在简单地重启工作器时安全地处理重命名的类等。

为了使QMan工作器能够获取并执行您的命令,您需要确保CommandSerializerInterface的实例能够识别它。QMan附带了一个名为GenericCommandSerializer的通用实现。让我们确保我们创建的类已正确注册

use Beanie\Beanie;
use QMan\WorkerBuilder;
use QMan\GenericCommandSerializer;

$serializer = new GenericCommandSerializer();
$serializer->registerCommandType('my.custom.command', CustomCommand::class);

$beanie = Beanie::pool(['localhost:11300']);
$worker = (new WorkerBuilder())
    ->withCommandSerializer($serializer)
    ->build($beanie);
    
$worker->run();

您可以通过收集类型与类映射,并将类型表示为常量来轻松地为您的应用程序提供未来兼容性

final class Commands
{
    const TYPE_CUSTOM_COMMAND = 'my.custom.command';
    
    public static function $map = [
        self::TYPE_CUSTOM_COMMAND => CustomCommand::class
    ];
}

QMan的GenericCommandSerializer附带一个registerCommandTypes($map)函数,可以处理上述情况。

配置

每个Worker都会接收到一个QManConfig实例。以下属性目前包含在内

(1):假设您正在使用默认的GenericJobFailureStrategy。当然,实现用于处理失败作业的自定义策略是完全可能的。

更改配置就像实例化QManConfig,设置您的配置偏好,并将其传递给CommandBuilder一样简单

use QMan\QManConfig;
use QMan\QManBuilder;
use Beanie\Beanie;

$config = new QManConfig();
$config->setTerminationSignals([SIGTERM, SIGQUIT]);

$beanie = Beanie::pool($servers);

$worker = (new WorkerBuilder())
    ->withQManConfig($config)
    ->build($beanie);

处理失败作业

默认情况下,qMan在处理失败作业时将采用一个非常简单的策略

  • 失败作业将被埋葬或再次释放
  • 如果作业连续失败少于maxTries次,它将带(连续失败的次数) * defaultFailureDelay再次释放
  • 否则,当它连续失败maxTries次时,它将被埋葬

可以通过实现JobFailureStrategyInterface(该接口扩展了PSR-3的LoggerAwareInterface和qMan的ConfigAwareInterface)轻松覆盖此行为。

use Psr\Log\LoggerAwareTrait;
use QMan\JobFailureStrategyInterface;
use QMan\Job;
use QMan\ConfigAwareTrait;

class MyCustomJobFailureStrategy implements JobFailureStrategyInterface
{
    use LoggerAwareTrait, ConfigAwareTrait;
    
    public function handleFailedJob(Job $job)
    {
        // Do stuff, like deleting the job after 10 total tries
        $stats = $job->stats();
        
        if ($stats['reserves'] > 10) {
            $this->logger->alert('Deleting job after failing to successfully execute over 10 times', ['job' => $job]);
            $job->delete();
        }
    }
}

use QMan\WorkerBuilder;

$worker = (new WorkerBuilder)->withJobFailureStrategy(new MyCustomJobFailureStrategy())->build([...]);

贡献

欢迎提交拉取请求。请确保代码质量(根据scrutinizer)不会太差,并且所有代码都经过彻底的单元测试。

在本地运行测试

$ git clone https://github.com/zwilias/qman.git
$ cd qman
$ composer install
$ vendor/bin/phpunit

许可证

版权所有(c)2015 Ilias Van Peer

在MIT许可证下发布,请参阅所附的LICENSE文件。