【问题标题】:High priority gearman jobs not being treated as high priority高优先级齿轮工作业未被视为高优先级
【发布时间】:2014-01-30 21:43:20
【问题描述】:

我正在 php 中实现一个“管理”钩子到我的齿轮工工作人员中。这是为了监控工人的整体统计数据,而不是工作。它还将提供一种允许工作人员取消注册、清理和终止的方法。我通过注册第二个函数来处理这些“管理员”请求来做到这一点。我想我可以发送一个“高”优先级的作业,而那个高优先级的作业应该抢占正常的优先级作业。情况似乎并非如此。

这是我正在运行的测试的简化版本:

工人:

<?php 
$gmw = new GearmanWorker();
$gmw->addServer();
$gmw->addFunction('Test', 'handleWork');
$gmw->addFunction('Admin', 'handleAdmin');
$gmw->setTimeout(10000); // 10s wait timeout for I/O activity
$pass_count = 0;
$job_count = 0;
$kill = false;
while (@$gmw->work() || $gmw->returnCode() == GEARMAN_TIMEOUT) {
    $pass_count++;
    if ($kill) {
        if ($gmw->returnCode() != GEARMAN_TIMEOUT) $gmw->unregisterAll();
        if ($gmw->returnCode() == GEARMAN_SUCCESS) $job_count++;
        print("\n\nKill command received, exiting...");
        stats(false);
        break;
    }
    if ($gmw->returnCode() == GEARMAN_TIMEOUT) {
        continue;
    } else if ($gmw->returnCode() != GEARMAN_SUCCESS) {
        $gmw->unregisterAll();
        print("\n\nGot Gearman Code \"" . $gmw->returnCode() . "\", exiting");
        break;
    }
    $job_count++;
}

function handleWork(GearmanJob $job) {
    print('.');
    usleep(100000);
    return '{"consumed": true}';
}

function handleAdmin(GearmanJob $job) {
    global $kill, $pass_count, $job_count;
    $payload = json_decode($job->workload());
    if ($pass_count) $pass_count--;
    if ($job_count) $job_count--;
    switch ($payload->action) {
        case 'kill':
            $kill = true;
            return json_encode(array(
                'message' => 'Kill request received',
            ));

        case 'stats':
            return json_encode(stats(true));
    }
}

function stats($return=true) {
    global $pass_count, $job_count;
    $obj = array(
        'pass_count' => $pass_count,
        'job_count' => $job_count,
    );
    if ($return) return $obj;

    foreach ($obj as $k => $v) {
        print("\n" . $k . ":\t" . $v);
    }
    print("\n");
}

CLIENT 1(向工人发送正常工作)

<?php
$gmc = new GearmanClient();
$gmc->addServer();

while (true) {
    print('.');
    for ($i=0; $i<100; $i++) {
        $gmc->addTaskBackground('Test', '{"foo":"bar"}');
    }
    $gmc->runTasks();
    sleep(15);
}

CLIENT 2(发送请求以获取统计信息)

<?php
$gmc = new GearmanClient();
$gmc->addServer();
$gmc->setCompleteCallback('output');
$gmc->addTaskHigh('Admin', '{"action":"stats"}');
$gmc->runTasks();

function output(GearmanTask $task) {
    foreach (json_decode($task->data()) as $k => $v) {
        print("\n$k:\t$v");
    }
    print("\n");
}

CLIENT 3(发送请求杀死工人)

<?php
$gmc = new GearmanClient();
$gmc->addServer();
$gmc->setCompleteCallback('output');
$gmc->addTaskHigh('Admin', '{"action":"kill"}');
$gmc->runTasks();

function output(GearmanTask $task) {
    foreach (json_decode($task->data()) as $k => $v) {
        print("\n$k:\t$v");
    }
    print("\n");
}

我做错了吗?有一个更好的方法吗?请注意,运行 WORKER 和 CLIENT 1 是一个无限循环。当我运行 CLIENT 2 或 CLIENT 3 时,它总是等到 CLIENT 1 发送的前 100 个作业完成后再运行提交的作业。

【问题讨论】:

  • 我认为这是因为 gearman 不会向忙碌的工作人员发送任何任务(无论优先级如何)。

标签: php multithreading gearman


【解决方案1】:

4年后你可能对此不再感兴趣,但我还是会添加一个答案,因为答案很有趣。

Gearmand 仅按每个函数的优先级 来排序作业的执行。 有两种方法可以解决此限制:

  • 运行两名工作人员,一名用于“测试”,一名用于“管理员”
  • 运行单个工作器,但在 “测试”(!)之前注册“Admin”。这是因为 Gearmand 首先按功能挑选新工作,然后按优先级挑选新工作。

另见https://github.com/gearman/gearmand/issues/173

【讨论】:

    【解决方案2】:

    听起来您需要解决您的设置问题。使用像 supervisord 这样的任务主管来操作多个 gearmand 工作人员,然后您可以设计一种很好的方法让多个工作人员尊重您分配的优先级,同时 supervisord 确保您有必要数量的工作人员在运行。

    强大,有效。我正在使用这种类型的逻辑来启动和关闭 AMI,以对应用服务器请求工作人员的视频进行转码。

    祝你好运!

    http://supervisord.org

    【讨论】:

    • 我打算使用 Supervisord,但它不能处理这部分,除非我理解错了。 Supervisord 是否优雅地杀死工作人员,或跟踪给定工作人员处理了多少工作?
    • Supervisor 确保进程启动并运行,因此您要做的就是对其进行配置以保持工作人员可用。使用 gearman,您需要工人来完成您的任务。您的工作人员一直在运行,并且只有在任务排队时才能真正工作。
    猜你喜欢
    • 2013-02-13
    • 2014-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-22
    • 2017-02-17
    • 1970-01-01
    相关资源
    最近更新 更多