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
This commit is contained in:
Aaron Schulz 2015-08-19 16:33:03 -07:00
parent 29b5bf4de9
commit 0a1c04beae
5 changed files with 74 additions and 2 deletions

View file

@ -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 ====

View file

@ -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
*/

View file

@ -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.
*

View file

@ -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 );
}
}
/**

View file

@ -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;
}
}
/**