EasySwoole RPC 自定义注册中心

EasySwoole 默认为通过UDP广播的方式来实现无主化的服务发现。但有些情况,不方便用UDP广播的情况下,那么EasySwoole支持你自定义一个节点管理器,来变更服务发现方式。

例如用Redis来实现

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: yf
  5. * Date: 2019-02-25
  6. * Time: 14:46
  7. */
  8. namespace EasySwoole\Rpc\NodeManager;
  9. use EasySwoole\Component\Pool\PoolManager;
  10. use EasySwoole\Rpc\Config;
  11. use EasySwoole\Rpc\ServiceNode;
  12. use EasySwoole\Utility\Random;
  13. class RedisManager implements NodeManagerInterface
  14. {
  15. const KEY = '__rpcRedisKey';
  16. private $pool;
  17. /**
  18. * 初始化服务节点管理器
  19. * RedisManager constructor.
  20. * @param Config $config
  21. */
  22. public function __construct(Config $config)
  23. {
  24. $config = $config->getExtra();
  25. //获取redis连接
  26. PoolManager::getInstance()->registerAnonymous('__rpcRedis', function () use ($config) {
  27. $redis = new \Redis();
  28. $redis->connect($config['host'], $config['port']);
  29. if (!empty($config['auth'])) {
  30. $redis->auth($config['auth']);
  31. }
  32. $redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP);
  33. return $redis;
  34. });
  35. $this->pool = PoolManager::getInstance()->getPool('__rpcRedis');
  36. }
  37. /**
  38. * 获取所有服务
  39. * getServiceNodes
  40. * @param string $serviceName
  41. * @param string|null $version
  42. * @return array
  43. * @author Tioncico
  44. * Time: 9:38
  45. */
  46. function getServiceNodes(string $serviceName, ?string $version = null): array
  47. {
  48. $list = [];
  49. $nodeList = $this->allServiceNodes();//获取所有服务
  50. foreach ($nodeList as $item) {
  51. $serviceNode = new ServiceNode($item);
  52. if ($serviceNode->getServiceName() == $serviceName) {
  53. if ($version !== null && $serviceNode->getServiceVersion() != $version) {
  54. continue;
  55. }
  56. $list[$serviceNode->getNodeId()] = $serviceNode->toArray();
  57. }
  58. }
  59. return $list;
  60. }
  61. /**
  62. * 获取某个服务节点的详情
  63. * getServiceNode
  64. * @param string $serviceName
  65. * @param string|null $version
  66. * @return ServiceNode|null
  67. * @author Tioncico
  68. * Time: 9:39
  69. */
  70. function getServiceNode(string $serviceName, ?string $version = null): ?ServiceNode
  71. {
  72. $list = $this->getServiceNodes($serviceName, $version);
  73. $num = count($list);
  74. if ($num == 0) {
  75. return null;
  76. }
  77. return new ServiceNode(Random::arrayRandOne($list));
  78. }
  79. /**
  80. * 取所有节点的列表数据
  81. * allServiceNodes
  82. * @return array
  83. * @author Tioncico
  84. * Time: 9:39
  85. */
  86. function allServiceNodes(): array
  87. {
  88. $list = [];
  89. if ($obj = $this->pool->getObj()) {
  90. $nodeList = $obj->hGetAll(self::KEY);
  91. $this->pool->recycleObj($obj);
  92. foreach ($nodeList as $key => $serviceNode) {
  93. if ($serviceNode->getNodeExpire() !== null && time() > $serviceNode->getNodeExpire()) {
  94. $this->deleteServiceNode($serviceNode);//超时删除
  95. continue;
  96. }
  97. $list[] = $serviceNode->toArray();
  98. }
  99. }
  100. return $list;
  101. }
  102. /**
  103. * 删除某个节点
  104. * deleteServiceNode
  105. * @param ServiceNode $serviceNode
  106. * @return bool
  107. * @author Tioncico
  108. * Time: 9:39
  109. */
  110. function deleteServiceNode(ServiceNode $serviceNode): bool
  111. {
  112. if ($obj = $this->pool->getObj()) {
  113. $obj->hDel(self::KEY, $serviceNode->getNodeId());
  114. $this->pool->recycleObj($obj);
  115. return true;
  116. }
  117. return false;
  118. }
  119. /**
  120. * 注册服务节点
  121. * registerServiceNode
  122. * @param ServiceNode $serviceNode
  123. * @return bool
  124. * @author Tioncico
  125. * Time: 9:39
  126. */
  127. function registerServiceNode(ServiceNode $serviceNode): bool
  128. {
  129. if ($obj = $this->pool->getObj()) {
  130. $obj->hSet(self::KEY, $serviceNode->getNodeId(), $serviceNode);
  131. $this->pool->recycleObj($obj);
  132. return true;
  133. }
  134. return false;
  135. }
  136. }

注意,设置自定义节点管理器后,就不再需要启用UDP定时广播进程了。请在创建RPC实例后,自己创建一个ServiceNode对象,刷新到注册中心。节点下线也是同理,在你服务关闭的时候,向节点管理器下线该节点。