restrict to one sleep per bucket. A second sleep while already sleeping results in a block.

This commit is contained in:
Brian Quinion
2012-12-10 01:36:33 +00:00
parent 661338ff25
commit 01ea772255
3 changed files with 40 additions and 6 deletions

View File

@@ -26,15 +26,17 @@
$m->add('sleepCounter', 0); $m->add('sleepCounter', 0);
$iCurrentSleeping = $m->increment('sleepCounter'); $iCurrentSleeping = $m->increment('sleepCounter');
} }
if ($iCurrentSleeping >= CONST_ConnectionBucket_MaxSleeping) if ($iCurrentSleeping >= CONST_ConnectionBucket_MaxSleeping || isBucketSleeping($aBucketKeys))
{ {
// Too many threads sleeping already. This becomes a hard block. // Too many threads sleeping already. This becomes a hard block.
$fBucketVal = doBucket($aBucketKeys, CONST_ConnectionBucket_BlockLimit, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_BlockLimit); $fBucketVal = doBucket($aBucketKeys, CONST_ConnectionBucket_BlockLimit, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_BlockLimit);
} }
else else
{ {
setBucketSleeping($aBucketKeys, true);
sleep(($fBucketVal - CONST_ConnectionBucket_WaitLimit)/CONST_ConnectionBucket_LeakRate); sleep(($fBucketVal - CONST_ConnectionBucket_WaitLimit)/CONST_ConnectionBucket_LeakRate);
$fBucketVal = doBucket($aBucketKeys, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_BlockLimit); $fBucketVal = doBucket($aBucketKeys, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_BlockLimit);
setBucketSleeping($aBucketKeys, false);
} }
$m->decrement('sleepCounter'); $m->decrement('sleepCounter');
} }
@@ -48,3 +50,4 @@
} }
header('Content-type: text/html; charset=utf-8'); header('Content-type: text/html; charset=utf-8');

View File

@@ -26,7 +26,7 @@
$aCurrentBlock = $m->get($sKey); $aCurrentBlock = $m->get($sKey);
if (!$aCurrentBlock) if (!$aCurrentBlock)
{ {
$aCurrentBlock = array($iRequestCost, $t); $aCurrentBlock = array($iRequestCost, $t, false);
} }
else else
{ {
@@ -87,6 +87,36 @@
return $iMaxVal; return $iMaxVal;
} }
function isBucketSleeping($asKey)
{
$m = getBucketMemcache();
if (!$m) return false;
foreach($asKey as $sKey)
{
$aCurrentBlock = $m->get($sKey);
if ($aCurrentBlock[2]) return true;
}
return false;
}
function setBucketSleeping($asKey, $bVal)
{
$m = getBucketMemcache();
if (!$m) return false;
$iMaxVal = 0;
$t = time();
foreach($asKey as $sKey)
{
$aCurrentBlock = $m->get($sKey);
$aCurrentBlock[2] = $bVal;
$m->set($sKey, $aCurrentBlock, $t + 1 + $aCurrentBlock[0]/CONST_ConnectionBucket_LeakRate);
}
return true;
}
function byValue1($a, $b) function byValue1($a, $b)
{ {
if ($a[1] == $b[1]) if ($a[1] == $b[1])
@@ -120,6 +150,7 @@
$aBlockedList[$sKey] = array( $aBlockedList[$sKey] = array(
'totalBlocks' => $aDetails[0], 'totalBlocks' => $aDetails[0],
'lastBlockTimestamp' => $aDetails[1], 'lastBlockTimestamp' => $aDetails[1],
'isSleeping' => (isset($aCurrentBlock[2])?$aCurrentBlock[2]:false),
'currentBucketSize' => $iCurrentBucketSize, 'currentBucketSize' => $iCurrentBucketSize,
'currentlyBlocked' => $iCurrentBucketSize + (CONST_ConnectionBucket_Cost_Reverse) >= CONST_ConnectionBucket_BlockLimit, 'currentlyBlocked' => $iCurrentBucketSize + (CONST_ConnectionBucket_Cost_Reverse) >= CONST_ConnectionBucket_BlockLimit,
); );

View File

@@ -29,13 +29,13 @@
$aBlocks = getBucketBlocks(); $aBlocks = getBucketBlocks();
echo "\n"; echo "\n";
printf(" %-40s | %12s | %7s | %13s | %31s\n", "Key", "Total Blocks", "Current", "Still Blocked", "Last Block Time"); printf(" %-40s | %12s | %7s | %13s | %31s | %8s\n", "Key", "Total Blocks", "Current", "Still Blocked", "Last Block Time", "Sleeping");
printf(" %'--40s-|-%'-12s-|-%'-7s-|-%'-13s-|-%'-31s\n", "", "", "", "", ""); printf(" %'--40s-|-%'-12s-|-%'-7s-|-%'-13s-|-%'-31s-|-%'-8s\n", "", "", "", "", "", "");
foreach($aBlocks as $sKey => $aDetails) foreach($aBlocks as $sKey => $aDetails)
{ {
printf(" %-40s | %12s | %7s | %13s | %31s\n", $sKey, $aDetails['totalBlocks'], printf(" %-40s | %12s | %7s | %13s | %31s | %8s\n", $sKey, $aDetails['totalBlocks'],
(int)$aDetails['currentBucketSize'], $aDetails['currentlyBlocked']?'Y':'N', (int)$aDetails['currentBucketSize'], $aDetails['currentlyBlocked']?'Y':'N',
date("r", $aDetails['lastBlockTimestamp'])); date("r", $aDetails['lastBlockTimestamp']), $aDetails['isSleeping']?'Y':'N');
} }
echo "\n"; echo "\n";
} }