diff --git a/lib/init-website.php b/lib/init-website.php index 8f04d97d..445bbc7c 100644 --- a/lib/init-website.php +++ b/lib/init-website.php @@ -19,8 +19,24 @@ if ($fBucketVal > CONST_ConnectionBucket_WaitLimit && $fBucketVal < CONST_ConnectionBucket_BlockLimit) { - sleep(($fBucketVal - CONST_ConnectionBucket_WaitLimit)/CONST_ConnectionBucket_LeakRate); - $fBucketVal = doBucket($aBucketKeys, 0, 0, CONST_ConnectionBucket_BlockLimit); + $m = getBucketMemcache(); + $iCurrentSleeping = $m->increment('sleepCounter'); + if (false === $iCurrentSleeping) + { + $m->add('sleepCounter', 0); + $iCurrentSleeping = $m->increment('sleepCounter'); + } + if ($iCurrentSleeping >= CONST_ConnectionBucket_MaxSleeping) + { + // Too many threads sleeping already. This becomes a hard block. + $fBucketVal = doBucket($aBucketKeys, CONST_ConnectionBucket_BlockLimit, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_BlockLimit); + } + else + { + sleep(($fBucketVal - CONST_ConnectionBucket_WaitLimit)/CONST_ConnectionBucket_LeakRate); + $fBucketVal = doBucket($aBucketKeys, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_BlockLimit); + } + $m->decrement('sleepCounter'); } if (strpos(CONST_BlockedIPs, ','.$_SERVER["REMOTE_ADDR"].',') !== false || $fBucketVal >= CONST_ConnectionBucket_BlockLimit) diff --git a/lib/lib.php b/lib/lib.php index 0af91e2d..91fe21b2 100644 --- a/lib/lib.php +++ b/lib/lib.php @@ -919,9 +919,14 @@ function getBucketMemcache() { + static $m; + if (!CONST_ConnectionBucket_MemcacheServerAddress) return null; - $m = new Memcached(); - $m->addServer(CONST_ConnectionBucket_MemcacheServerAddress, CONST_ConnectionBucket_MemcacheServerPort); + if (!isset($m)) + { + $m = new Memcached(); + $m->addServer(CONST_ConnectionBucket_MemcacheServerAddress, CONST_ConnectionBucket_MemcacheServerPort); + } return $m; } diff --git a/settings/settings.php b/settings/settings.php index 65604035..6bf526ca 100644 --- a/settings/settings.php +++ b/settings/settings.php @@ -20,10 +20,13 @@ @define('CONST_ConnectionBucket_LeakRate', 1); @define('CONST_ConnectionBucket_BlockLimit', 10); @define('CONST_ConnectionBucket_WaitLimit', 6); + @define('CONST_ConnectionBucket_MaxSleeping', 10); @define('CONST_ConnectionBucket_Cost_Reverse', 1); @define('CONST_ConnectionBucket_Cost_Search', 2); @define('CONST_ConnectionBucket_Cost_Details', 3); + // Override this function to add an adjustment factor to the cost + // based on server load. e.g. getBlockingProcesses if (!function_exists('user_busy_cost')) { function user_busy_cost() diff --git a/utils/blocks.php b/utils/blocks.php index 4d323115..4732abb1 100755 --- a/utils/blocks.php +++ b/utils/blocks.php @@ -23,6 +23,9 @@ if ($aResult['list']) { + $iCurrentSleeping = $m->get('sleepCounter'); + echo "\n Sleeping blocks count: $iCurrentSleeping\n"; + $aBlocks = getBucketBlocks(); echo "\n"; printf(" %-40s | %12s | %7s | %13s | %16s | %31s\n", "Key", "Total Blocks", "Current", "Still Blocked", "Last Req Blocked", "Last Block Time"); @@ -36,5 +39,6 @@ if ($aResult['delete']) { + $m->set('sleepCounter', 0); clearBucketBlocks(); }