gpt4 book ai didi

php - Gearman 工作被传递给多个 worker (PHP)

转载 作者:搜寻专家 更新时间:2023-10-31 20:49:36 26 4
gpt4 key购买 nike

我遇到的问题是,在 PHP 应用程序中,Gearman 作业有时会传递给多个工作人员。我可以减少代码以将其复制到一个文件中。现在我不确定这是 Gearman 中的错误还是 pecl 库中的错误或者我的代码中的错误。

这里是重现错误的代码:

#!/usr/bin/php
<?php

// Try 'standard', 'exception' or 'exception-sleep'.
$sWorker = 'exception';



// Detect run mode "client" or "worker".
if (!isset($argv[1]))
$sMode = 'client';
else
$sMode = 'worker-' . $sWorker;

$sLogFilePath = __DIR__ . '/log.txt';

switch ($sMode) {

case 'client':

// Remove all queued test jobs and quit if there are test workers running.
prepare();

// Init the greaman client.
$Client= new GearmanClient;
$Client->addServer();

// Empty the log file.
file_put_contents($sLogFilePath, '');

// Start some worker processes.
$aPids = array();
for ($i = 0; $i < 100; $i++)
$aPids[] = exec('php ' . __FILE__ . ' worker > /dev/null 2>&1 & echo $!');

// Start some jobs. Also try doHigh(), doBackground() and
// doBackgroundHigh();
for ($i = 0; $i < 50; $i++)
$Client->doNormal('test', $i);

// Wait a second (when running jobs in background).
// sleep(1);

// Prepare the log file entries.
$aJobs = array();
$aLines = file($sLogFilePath);
foreach ($aLines as $sLine) {
list($sTime, $sPid, $sHandle, $sWorkload) = $aAttributes = explode("\t", $sLine);
$sWorkload = trim($sWorkload);
if (!isset($aJobs[$sWorkload]))
$aJobs[$sWorkload] = array();
$aJobs[$sWorkload][] = $aAttributes;
}

// Remove all jobs that have been passed to only one worker as expected.
foreach ($aJobs as $sWorkload => $aJob) {
if (count($aJob) === 1)
unset($aJobs[$sWorkload]);
}

echo "\n\n";

if (empty($aJobs))
echo "No job has been passed to more than one worker.";
else {
echo "Those jobs has been passed more than one times to a worker:\n";
foreach ($aJobs as $sWorload => $aJob) {

echo "\nJob #" . $sWorload . ":\n";
foreach ($aJob as $aAttributes)
echo " $aAttributes[2] (Worker PID: $aAttributes[1])\n";
}
}

echo "\n\n";

// Kill all started workers.
foreach ($aPids as $sPid)
exec('kill ' . $sPid . ' > /dev/null 2>&1');

break;

case 'worker-standard':
$Worker = new GearmanWorker;
$Worker->addServer();
$Worker->addFunction('test', 'logJob');
$bShutdown = false;
while ($Worker->work())
if ($bShutdown)
continue;
break;

case 'worker-exception':
try {
$Worker = new GearmanWorker;
$Worker->addServer();
$Worker->addFunction('test', 'logJob');
$bShutdown = false;
while ($Worker->work())
if ($bShutdown)
throw new \Exception;

} catch (\Exception $E) {
}
break;

case 'worker-exception-sleep':
try {
$Worker = new GearmanWorker;
$Worker->addServer();
$Worker->addFunction('test', 'logJob');
$bShutdown = false;
while ($Worker->work())
{
if ($bShutdown) {
sleep(1);
throw new \Exception;
}
}
} catch (\Exception $E) {
}
break;
}

function logJob(\GearmanJob $Job)
{
global $bShutdown, $sLogFilePath;
$sLine = microtime(true) . "\t" . getmypid() . "\t" . $Job->handle() . "\t" . $Job->workload() . "\n";
file_put_contents($sLogFilePath, $sLine, FILE_APPEND);
$bShutdown = true;
}


function prepare()
{
$rGearman = fsockopen('127.0.0.1', '4730', $iErrno, $sErrstr, 3);
$aBuffer = array();
fputs ($rGearman, 'STATUS' . PHP_EOL);
stream_set_timeout($rGearman, 1);
while (!feof($rGearman))
if ('.' . PHP_EOL !== $sLine = fgets($rGearman, 128))
$aBuffer[] = $sLine;
else
break;
fclose($rGearman);

$bJobsInQueue = false;
$bWorkersRunning = false;
foreach ($aBuffer as $sFunctionLine) {
list($sFunctionName, $iQueuedJobs, $iRunningJobs, $iWorkers) = explode("\t", $sFunctionLine);
if ('test' === $sFunctionName) {
if (0 != $iQueuedJobs)
$bJobsInQueue = true;
if (0 != $iWorkers)
$bWorkersRunning = true;;
}
}

// Exit if there are workers running.
if ($bWorkersRunning)
die("There are some Gearman workers running that have registered a 'test' function. Please stop these workers and run again.\n\n");

// If there are test jobs in the queue start a worker that eat up the jobs.
if ($bJobsInQueue) {
$sPid = exec('gearman -n -w -f test > /dev/null 2>&1 & echo $!');
sleep(1);
exec ("kill $sPid > /dev/null 2>&1");
// Repeat this method to make sure all jobs are removed.
prepare();
}
}

当您在命令行上运行此代码时,它应该输出 "No job
已传递给多个工作人员。”
但它总是输出一些已传递给多个工作人员的工作列表。如果设置 则不会出现错误$sWorker = 'standard';'exception-sleep'

如果您可以运行代码并告诉我您是否能够重现代码中是否存在错误,这将对我有很大帮助。

最佳答案

与 Gearman 0.24、PECL lib 1.0.2 有完全相同的问题。每次都能用您的脚本重现错误。

旧版本的 Gearman(我认为是 0.14)过去工作正常。

将 Gearman 升级到 0.33 解决了这个问题。

关于php - Gearman 工作被传递给多个 worker (PHP),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9617721/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com