resque/php-resque

Redis支持的库,用于创建后台任务并在稍后处理它们。基于Ruby的resque。

v1.3.6 2020-04-16 16:39 UTC

This package is auto-updated.

Last update: 2024-08-28 21:31:07 UTC


README

PHP Resque是一个Redis支持的库,用于创建后台任务,将这些任务放入一个或多个队列中,并在稍后处理它们。

PHP-Resque Logo

License (MIT) PHP Version Latest Version Latest Unstable Version Downloads

Build Status Dependency Status

Latest Release Latest Release Date Commits Since Latest Release Maintenance Status

Contributors Chat on Slack

背景

Resque由GitHub首创,用Ruby编写。您在这里看到的是将Resque的worker和enqueue系统直接移植到PHP的几乎直接版本。

有关Resque的更多信息,请访问官方GitHub项目:https://github.com/resque/resque

有关更多信息,请参阅GitHub博客的启动帖子:http://github.com/blog/542-introducing-resque

PHP端口不包括自己的网页界面来查看队列状态,因为数据存储的格式与Resque的Ruby版本完全相同。

PHP端口提供了与Ruby版本几乎相同的特性

  • 可以将工作者分散到多台机器上
  • 包括对优先级(队列)的支持
  • 具有抵抗内存泄露(分叉)的能力
  • 预期会失败

它还支持以下附加功能

  • 具有跟踪作业状态的能力
  • 如果分叉子进程在运行作业时没有以状态码0退出,则将作业标记为失败
  • 具有内置的setUptearDown方法支持,分别称为作业前和作业后方法

此外,它还包括php-resque-scheduler,它是resque-scheduler的PHP端口,它为Resque添加了对未来项目排程的支持。它已被设计成与Ruby插件几乎直接复制

目前,php-resque-scheduler仅支持延迟作业,即推送作业到队列并在特定时间戳或几秒钟后运行的能力。计划在未来版本中添加对重复作业(类似于CRON)的支持。

此端口最初由Chris Boulton制作,并由社区维护。有关更多历史信息,请参阅https://github.com/chrisboulton/php-resque

需求

  • PHP 5.3+
  • Redis 2.2+
  • 可选但推荐:Composer

入门

当php-resque作为项目内的Composer包安装时,使用php-resque最容易。Composer不是必需的,但它使生活变得更简单。

如果您不熟悉Composer,请参阅https://getcomposer.org.cn/

  1. 运行composer require resque/php-resque

  2. 如果您还没有这样做,请将Composer的autoload添加到项目的初始化文件中。(示例)

require 'vendor/autoload.php';

作业

排队作业

作业如下排队

// Required if redis is located elsewhere
Resque\Resque::setBackend('localhost:6379');

$args = array(
          'name' => 'Chris'
        );
Resque\Resque::enqueue('default', 'My_Job', $args);

定义作业

每个作业都应该在其自己的类中,并包含一个perform方法。

class My_Job
{
    public function perform()
    {
        // Work work work
        echo $this->args['name'];
    }
}

当作业运行时,该类将被实例化,任何参数都将作为数组设置在实例化的对象上,并且可以通过$this->args访问。

作业抛出的任何异常都会导致作业失败 - 请在此处小心,并确保您处理了不应导致作业失败的异常。

任务也可以有setUptearDown方法。如果定义了setUp方法,它将在perform方法运行之前被调用。如果定义了tearDown方法,它将在任务完成后被调用。

class My_Job
{
    public function setUp()
    {
        // ... Set up environment for this job
    }

    public function perform()
    {
        // .. Run job
    }

    public function tearDown()
    {
        // ... Remove environment for this job
    }
}

出队任务

此方法可用于方便地从队列中移除一个任务。

// Removes job class 'My_Job' of queue 'default'
Resque\Resque::dequeue('default', ['My_Job']);

// Removes job class 'My_Job' with Job ID '087df5819a790ac666c9608e2234b21e' of queue 'default'
Resque\Resque::dequeue('default', ['My_Job' => '087df5819a790ac666c9608e2234b21e']);

// Removes job class 'My_Job' with arguments of queue 'default'
Resque\Resque::dequeue('default', ['My_Job' => array('foo' => 1, 'bar' => 2)]);

// Removes multiple jobs
Resque\Resque::dequeue('default', ['My_Job', 'My_Job2']);

如果没有提供任务,此方法将出队所有匹配提供的队列的任务。

// Removes all jobs of queue 'default'
Resque\Resque::dequeue('default');

跟踪任务状态

php-resque 有能力对队列中的任务进行基本状态跟踪。状态信息将允许您检查任务是否在队列中,是否正在运行,是否已完成或已失败。

要跟踪任务的状态,将true作为Resque\Resque::enqueue的第四个参数传递。将返回用于跟踪任务状态的令牌

$token = Resque\Resque::enqueue('default', 'My_Job', $args, true);
echo $token;

要获取任务的状态

$status = new Resque\Job\Status($token);
echo $status->get(); // Outputs the status

任务状态定义为Resque\Job\Status类中的常量。有效的状态包括

  • Resque\Job\Status::STATUS_WAITING - 任务仍在队列中
  • Resque\Job\Status::STATUS_RUNNING - 任务正在运行
  • Resque\Job\Status::STATUS_FAILED - 任务已失败
  • Resque\Job\Status::STATUS_COMPLETE - 任务已完成
  • false - 无法获取状态;令牌是否有效?

状态在任务完成后或失败后最多可保留24小时,然后自动过期。也可以通过调用状态类的stop()方法强制使状态过期。

获取任务PID

您可以通过Resque\Job\PID获取实际执行工作进程的PID。在分叉的操作系统上,这将是分叉进程的PID。

注意:在非分叉操作系统上,返回的PID将是工作进程本身的PID。

echo Resque\Job\PID::get($token);

如果perform尚未开始或已结束,函数返回0

延迟任务

引用Ruby resque-scheduler的文档

延迟任务是您希望在未来的某个时间点放入队列的一次性任务。经典示例是发送电子邮件

require 'Resque.php';
require 'Scheduler.php';

$in = 3600;
$args = array('id' => $user->id);
Resque\Scheduler::enqueueIn($in, 'email', 'SendFollowUpEmail', $args);

上述操作将任务存储在延迟队列中1小时,然后从队列中取出并将任务提交到Resque的email队列以供处理,一旦有可用的工人。

除了传递以秒为单位的相对时间外,还可以向enqueueAt方法提供时间戳,该时间戳可以是DateTime对象或包含UNIX时间戳的整数

require 'Resque.php';
require 'Scheduler.php';

$time = 1332067214;
Resque\Scheduler::enqueueAt($time, 'email', 'SendFollowUpEmail', $args);

$datetime = new DateTime('2012-03-18 13:21:49');
Resque\Scheduler::enqueueAt($datetime, 'email', 'SendFollowUpEmail', $args);

注意:resque-scheduler不保证任务将在指定的时间触发。在指定的时间,resque-scheduler将从延迟队列中取出任务并将其推送到Resque的适当队列。下一个可用的Resque工人将拾取任务。为了尽可能快速地处理,请尽可能保持队列为空。

工人

工人的工作方式与Ruby工人完全相同。有关工人的完整文档,请参阅原始文档。

包含设置运行工人环境的bin/resque基本“启动运行”文件。通过Composer安装时为vendor/bin/resque

与Ruby版本的resque的相似之处在于,为了在所有环境中工作,而不是像Ruby那样只有一个环境,PHP端口对您的设置没有任何假设。

要启动一个工人,它与Ruby版本非常相似

$ QUEUE=file_serve php bin/resque

您负责告诉工人要包含哪个文件以开始应用程序。您通过设置APP_INCLUDE环境变量来完成此操作

$ QUEUE=file_serve APP_INCLUDE=../application/init.php php bin/resque

小贴士:使用Composer?很可能你不需要担心APP_INCLUDE,因为希望Composer也负责自动加载你的应用程序!

让你的应用程序启动还包括通过自动加载器或包含它们的方式告诉工作进程你的工作类。

或者,你也可以始终从你的应用程序中include('bin/resque')并完全跳过设置APP_INCLUDE。只是在做之前确保设置了各种环境变量(setenv)。

日志记录

该端口支持用于将日志记录到STDOUT的相同环境变量。设置VERBOSE将打印基本调试信息,而VVERBOSE将打印详细信息。

$ VERBOSE=1 QUEUE=file_serve bin/resque
$ VVERBOSE=1 QUEUE=file_serve bin/resque

优先级和队列列表

同样,优先级和队列列表功能与Ruby工作进程的工作方式完全相同。多个队列应使用逗号分隔,它们的顺序是它们被检查的顺序。

按照原始示例

$ QUEUE=file_serve,warm_cache bin/resque

file_serve队列将在检查warm_cache队列之前在每个迭代中始终检查新工作。

运行所有队列

所有队列都支持相同的方式,并按字母顺序处理

$ QUEUE='*' bin/resque

运行多个工作进程

可以通过提供COUNT环境变量同时启动多个工作进程

$ COUNT=5 bin/resque

但是请注意,每个工作进程都是其自己的子进程,并且原始进程一旦创建了COUNT个子进程就会关闭。如果你需要使用外部应用程序(如monit)来跟踪你的工作进程,你需要解决这个问题。

自定义前缀

当多个应用程序使用相同的Redis数据库时,最好使用自定义前缀来分离Resque数据。

$ PREFIX=my-app-name bin/resque

设置Redis后端

当Redis数据库与运行工作进程的计算机上的主机不同时,你必须设置REDIS_BACKEND环境变量

$ REDIS_BACKEND=my-redis-ip:my-redis-port bin/resque

分叉

与Ruby版本类似,支持的平台将在获取工作后立即进行分叉。分叉的子进程将在工作完成时退出。

与php-resque的不同之处在于,如果一个分叉的子进程没有优雅地退出(PHP错误等),php-resque将自动失败该工作。

信号

信号也在支持的平台上的工作方式与Resque的Ruby版本完全相同

  • QUIT - 等待工作完成处理然后退出
  • TERM / INT - 立即终止工作然后退出
  • USR1 - 立即终止工作但不要退出
  • USR2 - 暂停工作进程,不会处理新工作
  • CONT - 恢复工作进程。

进程标题/状态

Resque的Ruby版本有一个很酷的功能,即工作进程的进程标题会更新以指示工作进程正在做什么,任何分叉的子进程也会设置其进程标题,以运行工作。这有助于识别服务器上运行的过程及其Resque状态。

PHP默认情况下直到5.5都没有此功能。

存在一个PECL模块(http://pecl.php.net/package/proctitle),在5.5之前它向PHP添加了此功能,因此如果您想更新进程标题,则需要安装该PECL模块。php-resque将自动检测并使用它。

Resque调度器

resque-scheduler需要一种特殊的后台运行的工人。这个工人负责从调度/延迟队列中取出项目并将它们添加到Resque的队列中。这意味着为了执行延迟或计划的工作,该工作进程需要运行。

包括一个基本的“启动并运行”的bin/resque-scheduler文件,该文件设置了一个运行的工作环境(通过Composer安装时为vendor/bin/resque-scheduler)。它接受与php-resque主要工作进程相同的许多环境变量

  • REDIS_BACKEND - 要连接的Redis服务器
  • LOGGING - 启用将日志记录到STDOUT
  • VERBOSE - 启用详细日志记录
  • VVERBOSE - 启用非常详细的日志记录
  • INTERVAL - 在检查预定/延迟队列之前休眠这么长时间
  • APP_INCLUDE - 启动时包含此文件(用于启动您的应用)
  • PIDFILE - 将工作进程的PID写入此文件

使用bin/resque-scheduler启动resque-scheduler工作进程很简单:$ php bin/resque-scheduler

事件/钩子系统

php-resque有一个基本的事件系统,可以让您的应用自定义一些php-resque内部行为的操作。

您可以通过注册Resque\Event并提供一个回调来监听事件(如下所示),当事件被触发时执行该回调

Resque\Event::listen('eventName', [callback]);

[回调]可以是PHP中任何可以通过call_user_func_array调用的内容

  • 一个包含函数名称的字符串
  • 包含要调用的对象和方法的数组
  • 包含要调用的对象和静态方法的数组
  • 闭包(PHP 5.3+)

事件可能传递参数(如下文所述),因此您的回调应接受这些参数。

您可以通过调用Resque\Event::stopListening来停止监听事件,并提供与Resque\Event::listen相同的参数。

由您的应用负责注册事件监听器。当在应用中入队事件时,只需确保已加载php-resque并调用Resque\Event::listen即可。

当运行工作进程时,如果您通过默认的bin/resque脚本运行工作进程,您的APP_INCLUDE脚本应该初始化并注册操作所需的所有监听器。如果您有自己的工作进程管理器,那么注册监听器的责任再次由您承担。

extras目录中包含一个示例插件。

事件

beforeFirstFork

在工作进程初始化时调用一次。传入的参数是刚刚初始化的Resque\Worker\ResqueWorker实例。

beforeFork

在php-resque分叉运行作业之前调用。传入的参数包含即将运行的作业的Resque\JobHandler实例。

beforeFork父进程中触发。任何更改都将对工作进程的生命周期产生永久影响。

afterFork

在php-resque分叉运行作业(但在运行作业之前)时调用。传入的参数包含即将运行的作业的Resque\JobHandler实例。

afterFork在分叉出子进程以完成作业后触发。任何更改仅在工作进程处理作业期间有效。

beforePerform

在运行作业的setUpperform方法之前调用。传入的参数包含即将运行的作业的Resque\JobHandler实例。

您可以通过抛出Resque\Exceptions\DoNotPerformException异常来防止作业执行。任何其他抛出的异常都将被视为在作业中抛出,导致作业失败。

afterPerform

在运行作业的performtearDown方法之后调用。传入的参数包含刚刚运行的Resque\JobHandler实例。

抛出的任何异常都将被视为在作业中抛出,导致作业被标记为失败。

onFailure

每当作业失败时调用。传入的参数(按顺序)包括

  • 异常 - 作业失败时抛出的异常
  • Resque\JobHandler - 失败的作业

beforeEnqueue

在使用Resque\Resque::enqueue方法将作业入队之前立即调用。传入的参数(按顺序)包括

  • 类 - 要入队的作业的名称字符串
  • 参数 - 作业的参数数组
  • 队列 - 要入队的作业的队列名称字符串
  • ID - 包含要入队的任务令牌的字符串

您可以通过抛出 Resque\Exceptions\DoNotCreateException 异常来防止任务入队。

afterEnqueue

在调用 Resque\Resque::enqueue 方法将任务入队后调用。传入的参数(按此顺序)包括

  • Class - 包含计划任务的名称的字符串
  • Arguments - 传递给任务的参数数组
  • Queue - 包含将任务添加到的队列名称的字符串
  • ID - 包含入队任务的新令牌的字符串

afterSchedule

在将任务添加到调度后调用。传入的参数包括任务的时间戳、队列、任务的类名以及任务的参数。

beforeDelayedEnqueue

在从延迟队列中取出任务并即将将其添加到 Resque 队列之前立即调用。传入的参数包括任务的队列、任务的类名以及任务的参数。

步骤详解

要深入了解 php-resque 在幕后执行的操作(无需直接检查代码),请参阅 HOWITWORKS.md

贡献者

项目负责人

  • @chrisboulton

项目负责人

  • @danhunsaker
  • @rajibahmed
  • @steveklabnik

其他人

  • @acinader
  • @ajbonner
  • @andrewjshults
  • @atorres757
  • @benjisg
  • @biinari
  • @cballou
  • @chaitanyakuber
  • @charly22
  • @CyrilMazur
  • @d11wtq
  • @dceballos
  • @ebernhardson
  • @hlegius
  • @hobodave
  • @humancopy
  • @iskandar
  • @JesseObrien
  • @jjfrey
  • @jmathai
  • @joshhawthorne
  • @KevBurnsJr
  • @lboynton
  • @maetl
  • @matteosister
  • @MattHeath
  • @mickhrmweb
  • @Olden
  • @patrickbajao
  • @pedroarnal
  • @ptrofimov
  • @rayward
  • @richardkmiller
  • @Rockstar04
  • @ruudk
  • @salimane
  • @scragg0x
  • @scraton
  • @thedotedge
  • @tonypiper
  • @trimbletodd
  • @warezthebeef