LBFactorySimple.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <?php
  2. /**
  3. * Generator of database load balancing objects.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. * http://www.gnu.org/copyleft/gpl.html
  19. *
  20. * @file
  21. * @ingroup Database
  22. */
  23. namespace Wikimedia\Rdbms;
  24. use InvalidArgumentException;
  25. /**
  26. * A simple single-master LBFactory that gets its configuration from the b/c globals
  27. */
  28. class LBFactorySimple extends LBFactory {
  29. /** @var LoadBalancer */
  30. private $mainLB;
  31. /** @var LoadBalancer[] */
  32. private $externalLBs = [];
  33. /** @var array[] Map of (server index => server config map) */
  34. private $mainServers = [];
  35. /** @var array[][] Map of (cluster => server index => server config map) */
  36. private $externalServersByCluster = [];
  37. /** @var string */
  38. private $loadMonitorClass;
  39. /**
  40. * @see LBFactory::__construct()
  41. * @param array $conf Additional parameters include:
  42. * - servers : list of server config maps to Database::factory().
  43. * Additionally, the server maps should have a 'load' key, which is used to decide
  44. * how often clients connect to one server verses the others. A 'max lag' key should
  45. * also be set on server maps, indicating how stale the data can be before the load
  46. * balancer tries to avoid using it. The map can have 'is static' set to disable blocking
  47. * replication sync checks (intended for archive servers with unchanging data).
  48. * - externalClusters : map of cluster names to server arrays. The servers arrays have the
  49. * same format as "servers" above.
  50. */
  51. public function __construct( array $conf ) {
  52. parent::__construct( $conf );
  53. $this->mainServers = $conf['servers'] ?? [];
  54. foreach ( $this->mainServers as $i => $server ) {
  55. if ( $i == 0 ) {
  56. $this->mainServers[$i]['master'] = true;
  57. } else {
  58. $this->mainServers[$i]['replica'] = true;
  59. }
  60. }
  61. foreach ( ( $conf['externalClusters'] ?? [] ) as $cluster => $servers ) {
  62. foreach ( $servers as $index => $server ) {
  63. $this->externalServersByCluster[$cluster][$index] = $server;
  64. }
  65. }
  66. $this->loadMonitorClass = $conf['loadMonitorClass'] ?? LoadMonitor::class;
  67. }
  68. public function newMainLB( $domain = false, $owner = null ) {
  69. return $this->newLoadBalancer( $this->mainServers, $owner );
  70. }
  71. public function getMainLB( $domain = false ) {
  72. if ( $this->mainLB === null ) {
  73. $this->mainLB = $this->newMainLB( $domain, $this->getOwnershipId() );
  74. }
  75. return $this->mainLB;
  76. }
  77. public function newExternalLB( $cluster, $owner = null ) {
  78. if ( !isset( $this->externalServersByCluster[$cluster] ) ) {
  79. throw new InvalidArgumentException( "Unknown cluster '$cluster'." );
  80. }
  81. return $this->newLoadBalancer( $this->externalServersByCluster[$cluster], $owner );
  82. }
  83. public function getExternalLB( $cluster ) {
  84. if ( !isset( $this->externalLBs[$cluster] ) ) {
  85. $this->externalLBs[$cluster] = $this->newExternalLB( $cluster, $this->getOwnershipId() );
  86. }
  87. return $this->externalLBs[$cluster];
  88. }
  89. public function getAllMainLBs() {
  90. return [ self::CLUSTER_MAIN_DEFAULT => $this->getMainLB() ];
  91. }
  92. public function getAllExternalLBs() {
  93. $lbs = [];
  94. foreach ( array_keys( $this->externalServersByCluster ) as $cluster ) {
  95. $lbs[$cluster] = $this->getExternalLB( $cluster );
  96. }
  97. return $lbs;
  98. }
  99. private function newLoadBalancer( array $servers, $owner ) {
  100. $lb = new LoadBalancer( array_merge(
  101. $this->baseLoadBalancerParams( $owner ),
  102. [
  103. 'servers' => $servers,
  104. 'loadMonitor' => [ 'class' => $this->loadMonitorClass ],
  105. ]
  106. ) );
  107. $this->initLoadBalancer( $lb );
  108. return $lb;
  109. }
  110. public function forEachLB( $callback, array $params = [] ) {
  111. if ( $this->mainLB !== null ) {
  112. $callback( $this->mainLB, ...$params );
  113. }
  114. foreach ( $this->externalLBs as $lb ) {
  115. $callback( $lb, ...$params );
  116. }
  117. }
  118. }