myonlinestore/gearmanmanager

此包已被弃用且不再维护。作者建议使用 brianlmoon/gearmanmanager 包。

PHP守护进程,用于管理gearman工作进程

1.1.1 2021-04-22 08:48 UTC

This package is auto-updated.

Last update: 2021-04-22 11:28:14 UTC


README

PHP需求

  • PHP 5.2.? - 不确定具体版本
  • POSIX扩展
  • 进程控制扩展
  • pecl/gearman或Net_Gearman

为什么使用GearmanManager

运行Gearman工作进程可能是一项繁琐的任务。许多文件重复相同的代码来创建工作进程、连接到服务器、向工作进程添加功能等。GearmanManager的目的是使运行工作进程更像是一项运营任务,而不是开发任务。

基本思路是,一旦部署,你只需要编写实际执行工作的代码,而不需要重复设置工作进程。我们通过在指定目录中创建包含函数的文件来实现这一点。文件名决定了与gearmand服务器注册的函数。这极大地简化了函数注册过程。

工作原理

我们首先决定工作代码将放在哪里。以这个例子为例,假设我们创建一个名为worker_dir的目录来存放所有的工作代码。然后我们会创建类似这样的文件:(以下示例使用pecl/gearman语法。对于PEAR/Gearman,请参阅示例pear工作进程,以了解细微差别)

过程式

# cat worker_dir/example_function.php

function example_function($job, &$log) {

    $workload = $job->workload();

    // do work on $job here as documented in pecl/gearman docs

    // Log is an array that is passed in by reference that can be
    // added to for logging data that is not part of the return data
    $log[] = "Success";

    // return your result for the client
    return $result;

}

此代码的存在会向gearmand服务器注册一个名为example_function的函数。

面向对象

# cat worker_dir/ExampleFunction.php

class ExampleFunction {

    public function run($job, &$log) {

        $workload = $job->workload();

        // do work on $job here as documented in pecl/gearman docs

        // Log is an array that is passed in by reference that can be
        // added to for logging data that is not part of the return data
        $log[] = "Success";

        // return your result for the client
        return $result;

    }

}

此代码的存在会向gearmand服务器注册一个名为ExampleFunction的函数。

等等!还有更多

除了简化工作进程创建,GearmanManager还提供进程管理。如果一个进程崩溃,它会在其位置启动一个新的进程。你也可以配置工作进程在一段时间后死亡,以防止PHP使用过多的内存。

然后是向服务器推送新代码的问题。GearmanManager有一个选项来监视工作目录,并在检测到服务器上部署了新代码时重启工作进程。

关闭GearmanManager时,它将允许工作进程完成其工作后再退出。

高级功能

虽然启动起来很容易,但你也可以使用GearmanManager做些更高级的事情。

配置工作进程

默认情况下,GearmanManager确保至少有一个知道如何执行每个具有工作目录中文件的作业的工作进程。为了清楚起见,这意味着默认情况下将为每个函数创建一个进程。这显然不适合大多数生产系统。你可以通过几种方法自定义函数运行的进程数。

GearmanManager 的 ini 文件分为一个或多个部分。其中包括全局部分 [GearmanManager],每个函数可以有一个部分。例如,在上面的例子中可以是 [example_function] 或 [ExampleFunction]。全局部分有几个选项。代码中包含了一些示例 ini 文件。

worker_dir - 定义工作函数所在的目录。您可以通过逗号分隔来指定多个目录。

include - 这是一个列表,其中包含应由该服务器注册的工作函数。它可以设置为 *,以包含工作目录中定义的所有函数。如果未设置该选项,* 是默认行为。

count - 此设置定义应运行以执行所有函数的最小工作进程数。例如,如果将 count 设置为 10,则将启动 10 个进程,这些进程已注册执行所有函数。默认值为 0。

dedicated_count - 此设置定义应启动的进程数,这些进程将仅针对每个要注册的函数执行一个函数。例如,如果您的工作目录中有 5 个函数,并将 dedicated_count 设置为 2,则将为每个函数启动 2 个进程,因此总共有 10 个进程用于这项工作。默认值为 1。

max_worker_lifetime - 将此值设置为工作进程在死亡之前的最大秒数。在完成工作后,工作进程将检查其是否已超过最大生命周期,如果是,则退出。然后,管理进程将用注册执行退出进程所做相同工作的新工作进程来替换它。默认值为 1 小时。

auto_update - 如果设置为 1,则管理器将分叉一个辅助进程来监视工作目录的更改。如果找到新代码,则向父进程发送信号以杀死工作进程,以便可以加载新代码。

对于每个已注册的函数,您还可以为这些工作进程指定一些选项。

count - 将此设置为某个整数值将确保有那么多知道如何执行此函数的工作进程。这不能保证会有专用进程,只能保证某些进程将注册此函数。该进程也可能注册其他函数。

dedicated_count - 将此设置为某个整数值将确保启动了那么多进程,这些进程将仅为此函数执行。该进程将不会执行除此函数以外的任何工作。

日志数据

命令行中有许多选项。查看 -h 获取所有选项。日志是这些选项之一。因为配置的加载已记录,所以您必须在命令行上指定日志信息。您应该注意两个选项。

-v 此选项启用管理器和工作进程的详细输出。您可以通过添加更多和更多 v(-vvvv)来获取更多和更多的日志数据。它按这种方式扩展

-v      Logs only information about the start up and shutdown
-vv     Logs information about process creation and exiting
-vvv    Logs information about workers and the work they are doing
-vvvv   Logs debug information
-vvvvv  Logs crazy amounts of data about all manner of things

-l 您可以指定一个日志文件,日志数据将被发送到该文件。如果没有设置,则日志数据将被发送到 stdout。您还可以将其设置为 syslog,以便将日志数据发送到系统日志。

指定 Gearman 服务器

您可以通过两种方式指定服务器。它们可以是命令行或配置文件中的指定。

在命令行上,您可以使用 -h [HOST[:PORT][,[HOST[:PORT]]]]。例如:-h 10.1.1.1:4730,10.1.1.2:4730

在全局 [GearmanManager] 部分的配置文件中,您可以使用这些选项

host - 由逗号分隔的主机和端口。例如:10.1.1.1:4730,10.1.1.2:4730

运行守护进程

最小命令行是

# ./pecl-manager.php -c /path/to/config.ini

还有一些命令行选项对于运行守护进程很有用。

-P - 管理进程应存储pid文件的路径。也可以在ini文件中设置pid_file。

-d - 如果在命令行上设置,管理进程将以守护进程方式运行

-u - 以哪个用户运行守护进程。你也可以在ini文件中使用user。

调试

所以你构建了一个很棒的工人,但不知何故它死了,而error_log是空的?

GearmanManager偶尔使用抑制操作符(@),这使得调试变得有点困难,因为错误消息被静音。

解决方案是Xdebug的尖叫,设置它的步骤如下

  1. 安装Xdebug
  2. 配置它
  3. 受益!

安装

pecl install xdebug

配置

将以下内容放入你的xdebug.ini

zend_extension="/path/to/where/your/xdebug.so"
xdebug.scream = 1
xdebug.show_exception_trace = 1