ClusterTopClient.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <?php
  2. class ClusterTopClient extends TopClient {
  3. private static $dnsconfig;
  4. private static $syncDate = 0;
  5. private static $applicationVar;
  6. private static $cfgDuration = 10;
  7. public function __construct($appkey = "", $secretKey = "") {
  8. ClusterTopClient::$applicationVar = new ApplicationVar;
  9. $this->appkey = $appkey;
  10. $this->secretKey = $secretKey;
  11. $saveConfig = ClusterTopClient::$applicationVar->getValue();
  12. if ($saveConfig) {
  13. $tmpConfig = $saveConfig['dnsconfig'];
  14. ClusterTopClient::$dnsconfig = $this->object_to_array($tmpConfig);
  15. unset($tmpConfig);
  16. ClusterTopClient::$syncDate = $saveConfig['syncDate'];
  17. if (!ClusterTopClient::$syncDate) {
  18. ClusterTopClient::$syncDate = 0;
  19. }
  20. }
  21. }
  22. public function __destruct() {
  23. if (ClusterTopClient::$dnsconfig && ClusterTopClient::$syncDate) {
  24. ClusterTopClient::$applicationVar->setValue("dnsconfig", ClusterTopClient::$dnsconfig);
  25. ClusterTopClient::$applicationVar->setValue("syncDate", ClusterTopClient::$syncDate);
  26. ClusterTopClient::$applicationVar->write();
  27. }
  28. }
  29. public function execute($request = null, $session = null, $bestUrl = null) {
  30. $currentDate = date('U');
  31. $syncDuration = $this->getDnsConfigSyncDuration();
  32. $bestUrl = $this->getBestVipUrl($this->gatewayUrl, $request->getApiMethodName(), $session);
  33. if ($currentDate - ClusterTopClient::$syncDate > $syncDuration * 60) {
  34. $httpdns = new HttpdnsGetRequest;
  35. ClusterTopClient::$dnsconfig = json_decode(parent::execute($httpdns, null, $bestUrl)->result, true);
  36. $syncDate = date('U');
  37. ClusterTopClient::$syncDate = $syncDate;
  38. }
  39. return parent::execute($request, $session, $bestUrl);
  40. }
  41. private function getDnsConfigSyncDuration() {
  42. if (ClusterTopClient::$cfgDuration) {
  43. return ClusterTopClient::$cfgDuration;
  44. }
  45. if (!ClusterTopClient::$dnsconfig) {
  46. return ClusterTopClient::$cfgDuration;
  47. }
  48. $config = json_encode(ClusterTopClient::$dnsconfig);
  49. if (!$config) {
  50. return ClusterTopClient::$cfgDuration;
  51. }
  52. $config = ClusterTopClient::$dnsconfig['config'];
  53. $duration = $config['interval'];
  54. ClusterTopClient::$cfgDuration = $duration;
  55. return ClusterTopClient::$cfgDuration;
  56. }
  57. private function getBestVipUrl($url, $apiname = null, $session = null) {
  58. $config = ClusterTopClient::$dnsconfig['config'];
  59. $degrade = $config['degrade'];
  60. if (strcmp($degrade, 'true') == 0) {
  61. return $url;
  62. }
  63. $currentEnv = $this->getEnvByApiName($apiname, $session);
  64. $vip = $this->getVipByEnv($url, $currentEnv);
  65. if ($vip) {
  66. return $vip;
  67. }
  68. return $url;
  69. }
  70. private function getVipByEnv($comUrl, $currentEnv) {
  71. $urlSchema = parse_url($comUrl);
  72. if (!$urlSchema) {
  73. return null;
  74. }
  75. if (!ClusterTopClient::$dnsconfig['env']) {
  76. return null;
  77. }
  78. if (!array_key_exists($currentEnv, ClusterTopClient::$dnsconfig['env'])) {
  79. return null;
  80. }
  81. $hostList = ClusterTopClient::$dnsconfig['env'][$currentEnv];
  82. if (!$hostList) {
  83. return null;
  84. }
  85. $vipList = null;
  86. foreach ($hostList as $key => $value) {
  87. if (strcmp($key, $urlSchema['host']) == 0 && strcmp($value['proto'], $urlSchema['scheme']) == 0) {
  88. $vipList = $value;
  89. break;
  90. }
  91. }
  92. $vip = $this->getRandomWeightElement($vipList['vip']);
  93. if ($vip) {
  94. return $urlSchema['scheme']."://".$vip.$urlSchema['path'];
  95. }
  96. return null;
  97. }
  98. private function getEnvByApiName($apiName, $session = "") {
  99. $apiCfgArray = ClusterTopClient::$dnsconfig['api'];
  100. if ($apiCfgArray) {
  101. if (array_key_exists($apiName, $apiCfgArray)) {
  102. $apiCfg = $apiCfgArray[$apiName];
  103. $userFlag = $apiCfg['user'];
  104. $flag = $this->getUserFlag($session);
  105. if ($userFlag && $flag) {
  106. return $this->getEnvBySessionFlag($userFlag, $flag);
  107. } else {
  108. return $this->getRandomWeightElement($apiCfg['rule']);
  109. }
  110. }
  111. }
  112. return $this->getDeafultEnv();
  113. }
  114. private function getUserFlag($session) {
  115. if ($session && strlen($session) > 5) {
  116. if ($session[0] == '6' || $session[0] == '7') {
  117. return $session[strlen($session) - 1];
  118. } else if ($session[0] == '5' || $session[0] == '8') {
  119. return $session[5];
  120. }
  121. }
  122. return null;
  123. }
  124. private function getEnvBySessionFlag($targetConfig, $flag) {
  125. if ($flag) {
  126. $userConf = ClusterTopClient::$dnsconfig['user'];
  127. $cfgArry = $userConf[$targetConfig];
  128. foreach ($cfgArry as $key => $value) {
  129. if (in_array($flag, $value)) {
  130. return $key;
  131. }
  132. }
  133. } else {
  134. return null;
  135. }
  136. }
  137. private function getRandomWeightElement($elements) {
  138. $totalWeight = 0;
  139. if ($elements) {
  140. foreach ($elements as $ele) {
  141. $weight = $this->getElementWeight($ele);
  142. $r = $this->randomFloat() * ($weight + $totalWeight);
  143. if ($r >= $totalWeight) {
  144. $selected = $ele;
  145. }
  146. $totalWeight += $weight;
  147. }
  148. if ($selected) {
  149. return $this->getElementValue($selected);
  150. }
  151. }
  152. return null;
  153. }
  154. private function getElementWeight($ele) {
  155. $params = explode('|', $ele);
  156. return floatval($params[1]);
  157. }
  158. private function getElementValue($ele) {
  159. $params = explode('|', $ele);
  160. return $params[0];
  161. }
  162. private function getDeafultEnv() {
  163. return ClusterTopClient::$dnsconfig['config']['def_env'];
  164. }
  165. private static function startsWith($haystack, $needle) {
  166. return $needle === "" || strpos($haystack, $needle) === 0;
  167. }
  168. private function object_to_array($obj) {
  169. $_arr = is_object($obj) ? get_object_vars($obj) : $obj;
  170. foreach ($_arr as $key => $val) {
  171. $val = (is_array($val) || is_object($val)) ? $this->object_to_array($val) : $val;
  172. $arr[$key] = $val;
  173. }
  174. return $arr;
  175. }
  176. private function randomFloat($min = 0, $max = 1) {
  177. return $min + mt_rand() / mt_getrandmax() * ($max - $min);
  178. }
  179. }
  180. ?>