From: Aaron Schulz Date: Wed, 19 Aug 2015 23:33:03 +0000 (-0700) Subject: Added $wgDataCenterId/$wgDataCenterRoles X-Git-Tag: 1.31.0-rc.0~9613^2 X-Git-Url: http://git.cyclocoop.org/%24href?a=commitdiff_plain;h=0a1c04beae41a7fe6f57152dfd7c0bc9261528e0;p=lhc%2Fweb%2Fwiklou.git Added $wgDataCenterId/$wgDataCenterRoles * This is used to set sticky DC cookies to avoid session replication lag (which also makes sure ChronologyProtector works) Bug: T91816 Change-Id: I7bc2f8185a3c05cb3ca5ccc42d300eccffae48e1 --- diff --git a/RELEASE-NOTES-1.27 b/RELEASE-NOTES-1.27 index eb154396f3..1670552a02 100644 --- a/RELEASE-NOTES-1.27 +++ b/RELEASE-NOTES-1.27 @@ -16,6 +16,9 @@ production. 1000 for the latter) are now hard-coded. === New features in 1.27 === +* $wgDataCenterId and $wgDataCenterRoles where added, which will serve as + basic configuration settings needed for multi-datacenter setups. + $wgDataCenterUpdateStickTTL was also added. ==== External libraries ==== diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 69b4a24b88..2793161ea2 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -1868,6 +1868,32 @@ $wgDBservers = false; */ $wgLBFactoryConf = array( 'class' => 'LBFactorySimple' ); +/** + * The ID of the current data center + * @since 1.27 + */ +$wgDataCenterId = 'default'; + +/** + * Map of data center IDs to their role ("master" or "slave") + * + * Multiple data centers can be setup to handle MediaWiki, with HTTP + * POSTs routed to the master data center and GET/HEAD/OPTION routed to + * any data center (usually the closest to the end user). In such setups, + * this setting should be set to the appropriate value in the site + * config for each data center. + * @since 1.27 + */ +$wgDataCenterRoles = array( 'default' => 'master' ); + +/** + * After a state-changing request is done by a client, this determines + * how many seconds that client should keep using the master datacenter. + * This avoids unexpected stale or 404 responses due to replication lag. + * @since 1.27 + */ +$wgDataCenterUpdateStickTTL = 10; + /** * File to log database errors to */ diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 6fbc11d0d8..3b9a8826c7 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -3605,6 +3605,28 @@ function wfSplitWikiID( $wiki ) { return $bits; } +/** + * @see $wgDataCenterRoles + * @return string The current cluster ID + * @since 1.27 + */ +function wfDataCenter() { + global $wgDataCenterId; + + return $wgDataCenterId; +} + +/** + * @see $wgDataCenterRoles + * @return string The current cluster role; one of (master/slave) + * @since 1.27 + */ +function wfDataCenterRole() { + global $wgDataCenterId, $wgDataCenterRoles; + + return $wgDataCenterRoles[$wgDataCenterId]; +} + /** * Get a Database object. * diff --git a/includes/MediaWiki.php b/includes/MediaWiki.php index fbacb2504e..f3fb15825f 100644 --- a/includes/MediaWiki.php +++ b/includes/MediaWiki.php @@ -504,6 +504,14 @@ class MediaWiki { $factory->shutdown(); wfDebug( __METHOD__ . ' completed; all transactions committed' ); + + // Set a cookie to tell all CDN edge nodes to "stick" the user to the + // DC that handles this POST request (e.g. the "master" data center) + $request = $this->context->getRequest(); + if ( $request->wasPosted() && $factory->hasOrMadeRecentMasterChanges() ) { + $expires = time() + $this->config->get( 'DataCenterUpdateStickTTL' ); + $request->response()->setCookie( 'UseDC', 'master', $expires ); + } } /** diff --git a/includes/db/loadbalancer/LBFactory.php b/includes/db/loadbalancer/LBFactory.php index da0fe44c51..e5fb09435f 100644 --- a/includes/db/loadbalancer/LBFactory.php +++ b/includes/db/loadbalancer/LBFactory.php @@ -202,9 +202,9 @@ abstract class LBFactory { } /** - * Detemine if any master connection has pending changes. - * @since 1.23 + * Determine if any master connection has pending changes * @return bool + * @since 1.23 */ public function hasMasterChanges() { $ret = false; @@ -213,6 +213,19 @@ abstract class LBFactory { } ); return $ret; } + + /** + * Determine if any master connection has pending/written changes from this request + * @return bool + * @since 1.27 + */ + public function hasOrMadeRecentMasterChanges() { + $ret = false; + $this->forEachLB( function ( LoadBalancer $lb ) use ( &$ret ) { + $ret = $ret || $lb->hasOrMadeRecentMasterChanges(); + } ); + return $ret; + } } /**