ServerSwitch.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <?php
  2. /**
  3. * 用于多个域名之间的切换逻辑
  4. * Created by PhpStorm.
  5. * User: zhangdali
  6. * Date: 2016/12/5
  7. * Time: 下午4:29
  8. */
  9. class ServerSwitch {
  10. /**
  11. * 存储message的server
  12. * @var array Server
  13. */
  14. private $servers;
  15. private $feedback;
  16. private $sandbox;
  17. private $specified;
  18. private $emq;
  19. private $defaultServer;
  20. private $inited = false;
  21. private $lastRefreshTime;
  22. static $REFRESH_SERVER_HOST_INTERVAL = 300000;
  23. /**
  24. * @var ServerSwitch reference to singleton instance
  25. */
  26. private static $instance;
  27. /**
  28. * 通过延迟加载(用到时才加载)获取实例
  29. *
  30. * @return self
  31. */
  32. public static function getInstance() {
  33. if (!isset(self::$instance)) {
  34. $class = __CLASS__;
  35. self::$instance = new $class;
  36. }
  37. return self::$instance;
  38. }
  39. /**
  40. * 是否需要刷新host列表
  41. * @return bool
  42. */
  43. public function needRefreshHostList() {
  44. return !$this->inited ||
  45. $this->currentTimeMillis() - $this->lastRefreshTime >= self::$REFRESH_SERVER_HOST_INTERVAL;
  46. }
  47. /**
  48. * @param String $serverListStr : host:min:max:step,host:min:max:step,...
  49. */
  50. public function initialize($serverListStr) {
  51. if (!$this->needRefreshHostList()) {
  52. return;
  53. }
  54. $serverStrArr = explode(',', $serverListStr);
  55. $servers = array();
  56. $i = 0;
  57. foreach ($serverStrArr as $serverStr) {
  58. $sp = explode(":", $serverStr);
  59. if (count($sp) < 5) {
  60. $servers[$i] = $this->defaultServer;
  61. continue;
  62. }
  63. $servers[$i] = new Server($sp[0], intval($sp[1]), intval($sp[2]), intval($sp[3]), intval($sp[4]));
  64. if (!empty($this->servers)) {
  65. foreach ($this->servers as $server) {
  66. if (strcmp($server->getHost(), $servers[$i]->getHost())) {
  67. $servers[$i]->setPriority($server->getPriority());
  68. }
  69. }
  70. }
  71. $i++;
  72. }
  73. $this->inited = true;
  74. $this->lastRefreshTime = $this->currentTimeMillis();
  75. $this->servers = $servers;
  76. }
  77. /**
  78. * @param PushRequestPath $requestPath
  79. */
  80. public function &selectServer($requestPath) {
  81. if (isset(\Constants::$host)) {
  82. return $this->specified->setHost(\Constants::$host);
  83. }
  84. if (\Constants::$sandbox) {
  85. return $this->sandbox;
  86. }
  87. switch ($requestPath->getRequestType()) {
  88. case \PushRequestType::FEEDBACK:
  89. return $this->feedback;
  90. case \PushRequestType::EMQ:
  91. return $this->emq;
  92. default:
  93. return $this->selectMsgServer();
  94. }
  95. }
  96. private function selectMsgServer() {
  97. if (! \Constants::$autoSwitchHost || !$this->inited) {
  98. return $this->defaultServer;
  99. }
  100. $allPriority = 0;
  101. $priorities = array();
  102. foreach ($this->servers as $server) {
  103. $priorities[] = $server->getPriority();
  104. $allPriority += $server->getPriority();
  105. }
  106. $randomPoint = mt_rand(0, $allPriority);
  107. $sum = 0;
  108. for ($i = 0; $i < count($priorities); $i++) {
  109. $sum += $priorities[$i];
  110. if ($randomPoint <= $sum) {
  111. return $this->servers[$i];
  112. }
  113. }
  114. return $this->defaultServer;
  115. }
  116. /**
  117. * 构造函数私有,不允许在外部实例化
  118. */
  119. private function __construct() {
  120. $this->feedback = new \Server(\Constants::HOST_PRODUCTION_FEEDBACK, 100, 100, 0, 0);
  121. $this->sandbox = new \Server(\Constants::HOST_SANDBOX, 100, 100, 0, 0);
  122. $this->specified = new \Server(\Constants::$host, 100, 100, 0, 0);
  123. $this->emq = new \Server(\Constants::HOST_EMQ, 100, 100, 0, 0);
  124. $this->defaultServer = new \Server(\Constants::HOST_PRODUCTION, 1, 90, 10, 5);
  125. $this->lastRefreshTime = $this->currentTimeMillis();
  126. }
  127. /**
  128. * 防止对象实例被克隆
  129. *
  130. * @return void
  131. */
  132. private function __clone() {
  133. }
  134. /**
  135. * 防止被反序列化
  136. *
  137. * @return void
  138. */
  139. private function __wakeup() {
  140. }
  141. /**
  142. * 获取当前时间(毫秒)
  143. * @return int
  144. */
  145. private function currentTimeMillis() {
  146. return ceil(microtime(true) * 1000);
  147. }
  148. }