123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- <?php
- /**
- * An interface for database load monitoring
- */
- interface LoadMonitor {
- /**
- * Construct a new LoadMonitor with a given LoadBalancer parent
- */
- function __construct( $parent );
-
- /**
- * Perform pre-connection load ratio adjustment.
- * @param array $loads
- * @param string $group The selected query group
- * @param string $wiki
- */
- function scaleLoads( &$loads, $group = false, $wiki = false );
- /**
- * Perform post-connection backoff.
- *
- * If the connection is in overload, this should return a backoff factor
- * which will be used to control polling time. The number of threads
- * connected is a good measure.
- *
- * If there is no overload, zero can be returned.
- *
- * A threshold thread count is given, the concrete class may compare this
- * to the running thread count. The threshold may be false, which indicates
- * that the sysadmin has not configured this feature.
- *
- * @param Database $conn
- * @param float $threshold
- */
- function postConnectionBackoff( $conn, $threshold );
- /**
- * Return an estimate of replication lag for each server
- */
- function getLagTimes( $serverIndexes, $wiki );
- }
- /**
- * Basic MySQL load monitor with no external dependencies
- * Uses memcached to cache the replication lag for a short time
- */
- class LoadMonitor_MySQL implements LoadMonitor {
- var $parent; // LoadBalancer
- function __construct( $parent ) {
- $this->parent = $parent;
- }
- function scaleLoads( &$loads, $group = false, $wiki = false ) {
- }
- function getLagTimes( $serverIndexes, $wiki ) {
- wfProfileIn( __METHOD__ );
- $expiry = 5;
- $requestRate = 10;
- global $wgMemc;
- if ( empty( $wgMemc ) )
- $wgMemc = wfGetMainCache();
-
- $masterName = $this->parent->getServerName( 0 );
- $memcKey = wfMemcKey( 'lag_times', $masterName );
- $times = $wgMemc->get( $memcKey );
- if ( $times ) {
- # Randomly recache with probability rising over $expiry
- $elapsed = time() - $times['timestamp'];
- $chance = max( 0, ( $expiry - $elapsed ) * $requestRate );
- if ( mt_rand( 0, $chance ) != 0 ) {
- unset( $times['timestamp'] );
- wfProfileOut( __METHOD__ );
- return $times;
- }
- wfIncrStats( 'lag_cache_miss_expired' );
- } else {
- wfIncrStats( 'lag_cache_miss_absent' );
- }
- # Cache key missing or expired
- $times = array();
- foreach ( $serverIndexes as $i ) {
- if ($i == 0) { # Master
- $times[$i] = 0;
- } elseif ( false !== ( $conn = $this->parent->getAnyOpenConnection( $i ) ) ) {
- $times[$i] = $conn->getLag();
- } elseif ( false !== ( $conn = $this->parent->openConnection( $i, $wiki ) ) ) {
- $times[$i] = $conn->getLag();
- }
- }
- # Add a timestamp key so we know when it was cached
- $times['timestamp'] = time();
- $wgMemc->set( $memcKey, $times, $expiry );
- # But don't give the timestamp to the caller
- unset($times['timestamp']);
- $lagTimes = $times;
- wfProfileOut( __METHOD__ );
- return $lagTimes;
- }
- function postConnectionBackoff( $conn, $threshold ) {
- if ( !$threshold ) {
- return 0;
- }
- $status = $conn->getStatus("Thread%");
- if ( $status['Threads_running'] > $threshold ) {
- return $status['Threads_connected'];
- } else {
- return 0;
- }
- }
- }
|