• EasySwoole RPC 自定义注册中心
    • 例如用Redis来实现

    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对象,刷新到注册中心。节点下线也是同理,在你服务关闭的时候,向节点管理器下线该节点。