RPC 组件配置及使用

配置

服务端配置

  1. <?php
  2. // 构造方法内用户可传入 节点管理器实现类(实现 `NodeManagerInterface` 接口的类) 默认为 `MemoryManager`
  3. $config = new \EasySwoole\Rpc\Config();
  4. /**
  5. * 服务端配置
  6. */
  7. // 设置服务名称
  8. $config->setServerName('User'); // 默认 EasySwoole
  9. // 设置节点id
  10. $config->setNodeId(\EasySwoole\Utility\Random::character(10)); // 可忽略 构造函数已经设置
  11. // 【必须设置】设置异常处理器,对 Service-Worker 和 AssistWorker 的异常进行处理,防止未捕获导致进程退出
  12. $config->setOnException(function (\Throwable $throwable) {
  13. });
  14. $serverConfig = $config->getServer();
  15. // 【必须设置】设置本机ip
  16. $serverConfig->setServerIp('127.0.0.1');
  17. // 设置工作进程数量
  18. $serverConfig->setWorkerNum(4);
  19. // 设置监听地址及端口
  20. $serverConfig->setListenAddress('0.0.0.0');
  21. $serverConfig->setListenPort('9600');
  22. // 设置服务端最大接受包大小
  23. $serverConfig->setMaxPackageSize(1024 * 1024 * 2);
  24. // 设置接收客户端数据时间
  25. $serverConfig->setNetworkReadTimeout(3);
  26. /**
  27. * 广播设置
  28. */
  29. $assistConfig = $config->getAssist();
  30. // 服务定时自刷新到节点管理器
  31. $assistConfig->setAliveInterval(5000);
  32. // 广播进程设置
  33. $serviceFinderConfig = $assistConfig->getUdpServiceFinder();
  34. // 监听地址和端口
  35. $serviceFinderConfig->setEnableListen(true);
  36. $serviceFinderConfig->setListenAddress('0.0.0.0');
  37. $serviceFinderConfig->setListenPort(9600);
  38. // 设置广播地址
  39. $serviceFinderConfig->setEnableBroadcast(true);
  40. $serviceFinderConfig->setBroadcastAddress(['127.0.0.1:9600', '127.0.0.1:9601']);
  41. $serviceFinderConfig->setBroadcastInterval(5000); // 5s 广播一次
  42. // 设置广播秘钥
  43. $serviceFinderConfig->setEncryptKey('EasySwoole');

广播配置需要在配置服务端时,进行配置。

客户端配置

  1. <?php
  2. // 构造方法内用户可传入 节点管理器实现类(实现 `NodeManagerInterface` 接口的类) 默认为 `MemoryManager`
  3. $config = new \EasySwoole\Rpc\Config();
  4. /**
  5. * 客户端设置
  6. *
  7. * 如果只是暴露rpc服务 不进行调用别的rpc服务 可不用设置
  8. */
  9. $clientConfig = $config->getClient();
  10. // 传输最大数据包大小
  11. $clientConfig->setMaxPackageSize(1024 * 1024 * 2);
  12. // 设置全局回调函数 成功及失败 $response->getStatus !== 0 全部为失败
  13. $clientConfig->setOnGlobalSuccess(function (\EasySwoole\Rpc\Protocol\Response $response){
  14. });
  15. $clientConfig->setOnGlobalFail(function (\EasySwoole\Rpc\Protocol\Response $response){
  16. });

注册服务

注册 rpc 服务

  1. <?php
  2. ###### 配置服务端 ######
  3. // 构造方法内用户可传入 节点管理器实现类(实现 `NodeManagerInterface` 接口的类) 默认为 `MemoryManager`
  4. $config = new \EasySwoole\Rpc\Config();
  5. // 设置服务名称
  6. $config->setServerName('User'); // 默认 EasySwoole
  7. // 设置节点id,可忽略,构造函数已经设置
  8. $config->setNodeId(\EasySwoole\Utility\Random::character(10)); //
  9. // 【必须设置】设置异常处理器,对 Service-Worker 和 AssistWorker 的异常进行处理,防止未捕获导致进程退出
  10. $config->setOnException(function (\Throwable $throwable) {
  11. });
  12. $serverConfig = $config->getServer();
  13. // 【必须设置】设置本机ip
  14. $serverConfig->setServerIp('127.0.0.1');
  15. /**
  16. * 注册服务
  17. */
  18. $rpc = new \EasySwoole\Rpc\Rpc($config);
  19. // 创建 ServiceOne 服务
  20. $serviceOne = new \App\RpcServices\ServiceOne();
  21. // 在 ServiceOne 服务中添加 ModuleOne 模块
  22. $serviceOne->addModule(new \App\RpcServices\ModuleOne());
  23. // 在 ServiceOne 服务中添加 ModuleTwo 模块
  24. $serviceOne->addModule(new \App\RpcServices\ModuleTwo());
  25. // 创建 ServiceTwo 服务
  26. $serviceTwo = new \App\RpcServices\ServiceTwo();
  27. // 在 ServiceTwo 服务中添加 ModuleOne 模块
  28. $serviceTwo->addModule(new \App\RpcServices\ModuleOne());
  29. // 在 ServiceTwo 服务中添加 ModuleTwo 模块
  30. $serviceTwo->addModule(new \App\RpcServices\ModuleTwo());
  31. // 添加服务到服务管理器
  32. $rpc->serviceManager()->addService($serviceOne);
  33. $rpc->serviceManager()->addService($serviceTwo);
  34. // 注册服务
  35. # $http = new \Swoole\Http\Server('0.0.0.0', 9501);
  36. $http = \EasySwoole\EasySwoole\ServerManager::getInstance()->getSwooleServer();
  37. $rpc->attachServer($http);

用户可以自行实现 Redis 节点管理器实现类(实现 NodeManagerInterface 接口即可),来完成 rpc 服务端的配置。下文将介绍使用默认节点管理器(即 MemoryManager)完成 rpc 服务端的配置、rpc 服务的注册及服务调用。

调用

客户端调用

  1. <?php
  2. $rpc = new \EasySwoole\Rpc\Rpc($config);
  3. $client = $rpc->client();
  4. // 添加请求(调用 ServiceOne 服务的 ModuleOne 模块的 action 方法)
  5. $ctx1 = $client->addRequest('ServiceOne.ModuleOne.action');
  6. // 设置请求参数
  7. $ctx1->setArg(['a','b','c']);
  8. $ctx1->setOnSuccess(function (\EasySwoole\Rpc\Protocol\Response $response){
  9. // 调用成功获得响应
  10. });
  11. $ctx1->setOnFail(function (\EasySwoole\Rpc\Protocol\Response $response){
  12. // 调用失败获得响应
  13. });
  14. // 添加请求(调用 ServiceTwo 服务的 ModuleOne 模块的 action 方法)
  15. $ctx2 = $client->addRequest('ServiceTwo.ModuleOne.action');
  16. // 设置请求参数
  17. $ctx2->setArg(['a','b','c']);
  18. $ctx2->setOnSuccess(function (\EasySwoole\Rpc\Protocol\Response $response){
  19. // 调用成功获得响应
  20. });
  21. $ctx2->setOnFail(function (\EasySwoole\Rpc\Protocol\Response $response){
  22. // 调用失败获得响应
  23. });

注意,当使用默认实现的节点管理器(即 MemoryManager)进行注册服务端时,在进行客户端调用时,请使用 \EasySwoole\Components\Di 组件保存 rpc 服务端注册服务完成后的实例或在 Swoole 中独立使用采用 use 引入 rpc 服务端注册服务完成后的实例,具体请看下文的使用示例。

节点管理器使用介绍

  1. <?php
  2. /** 节点管理器 */
  3. // 用户在调用rpc过程中 当发现节点不可用 可自行调用下线
  4. // 构造方法内用户可传入节点管理器实现`NodeManagerInterface` 默认`MemoryManager`
  5. $config = new \EasySwoole\Rpc\Config();
  6. $rpc = new \EasySwoole\Rpc\Rpc($config);
  7. $nodeManager = $rpc->getConfig()->getNodeManager();
  8. // 获取服务的所有节点
  9. $nodeManager->getNodes('serviceOne', 1);
  10. // 随机获取服务的一个节点
  11. $nodeManager->getNode('serviceOne', 1);
  12. // 下线一个服务节点
  13. $nodeManager->offline(new \EasySwoole\Rpc\Server\ServiceNode());
  14. // 刷新一个服务节点
  15. $nodeManager->alive(new \EasySwoole\Rpc\Server\ServiceNode());
  16. // 宕机一个服务节点
  17. $nodeManager->failDown(new \EasySwoole\Rpc\Server\ServiceNode());

基础使用

新建 App\RpcServices\ 文件夹,然后定义如下 服务类模块类

  1. 定义 ServiceOne 服务
  1. <?php
  2. namespace App\RpcServices;
  3. use EasySwoole\Rpc\Service\AbstractService;
  4. class ServiceOne extends AbstractService
  5. {
  6. function serviceName(): string
  7. {
  8. return 'ServiceOne';
  9. }
  10. }
  1. 定义 ServiceTwo 服务
  1. <?php
  2. namespace App\RpcServices;
  3. use EasySwoole\Rpc\Service\AbstractService;
  4. class ServiceTwo extends AbstractService
  5. {
  6. function serviceName(): string
  7. {
  8. return 'ServiceTwo';
  9. }
  10. }
  1. 定义 ModuleOne 模块
  1. <?php
  2. namespace App\RpcServices;
  3. use EasySwoole\Rpc\Service\AbstractServiceModule;
  4. class ModuleOne extends AbstractServiceModule
  5. {
  6. function moduleName(): string
  7. {
  8. return 'ModuleOne';
  9. }
  10. function args()
  11. {
  12. $this->response()->setResult($this->request()->getArg());
  13. }
  14. function action()
  15. {
  16. $this->response()->setMsg("ModuleOne hello action");
  17. }
  18. function exception()
  19. {
  20. throw new \Exception('the ModuleOne exception');
  21. }
  22. protected function onException(\Throwable $throwable)
  23. {
  24. $this->response()->setStatus(-1)->setMsg($throwable->getMessage());
  25. }
  26. }
  1. 定义 ModuleTwo 模块
  1. <?php
  2. namespace App\RpcServices;
  3. use EasySwoole\Rpc\Service\AbstractServiceModule;
  4. class ModuleTwo extends AbstractServiceModule
  5. {
  6. function moduleName(): string
  7. {
  8. return 'ModuleTwo';
  9. }
  10. function args()
  11. {
  12. $this->response()->setResult($this->request()->getArg());
  13. }
  14. function action()
  15. {
  16. $this->response()->setMsg("ModuleTwo hello action");
  17. }
  18. function exception()
  19. {
  20. throw new \Exception('the ModuleTwo exception');
  21. }
  22. protected function onException(\Throwable $throwable)
  23. {
  24. $this->response()->setStatus(-1)->setMsg($throwable->getMessage());
  25. }
  26. }

在 Swoole 中独立使用

  1. <?php
  2. use EasySwoole\Rpc\Config;
  3. use EasySwoole\Rpc\Protocol\Response;
  4. use EasySwoole\Rpc\Rpc;
  5. use Swoole\Http\Server;
  6. use App\RpcServices\ServiceOne;
  7. use App\RpcServices\ModuleOne;
  8. require 'vendor/autoload.php';
  9. // 配置 rpc 服务端
  10. $config = new Config();
  11. // 【必须设置】设置本机ip
  12. $config->getServer()->setServerIp('127.0.0.1');
  13. $rpc = new Rpc($config);
  14. // 创建 ServiceOne 服务
  15. $service = new ServiceOne();
  16. // 添加 ModuleOne 模块到 ServiceOne 服务中
  17. $service->addModule(new ModuleOne());
  18. // 添加 ServiceOne 服务到服务管理器中
  19. $rpc->serviceManager()->addService($service);
  20. $http = new Server('0.0.0.0', 9501);
  21. // 注册 rpc 服务
  22. $rpc->attachServer($http);
  23. // 使用 use 引入 rpc 服务端注册服务完成后的实例
  24. $http->on('request', function ($request, $response) use ($rpc) {
  25. // 客户端调用
  26. $client = $rpc->client();
  27. // 添加请求(调用 ServiceOne 服务的 ModuleOne 模块的 action 方法)
  28. $ctx2 = $client->addRequest('ServiceOne.ModuleOne.action');
  29. // 设置请求参数
  30. $ctx2->setArg('xxx');
  31. $rpcCallRet = '';
  32. // 设置调用成功执行回调
  33. $ctx2->setOnSuccess(function (Response $response) use (&$rpcCallRet) {
  34. // 调用成功获得响应
  35. var_dump($response->getMsg());
  36. $rpcCallRet = $response->getMsg();
  37. });
  38. // 设置调用失败执行回调
  39. $ctx2->setOnFail(function (Response $response) use (&$rpcCallRet) {
  40. // 调用失败获得响应
  41. var_dump($response->getMsg());
  42. $rpcCallRet = $response->getMsg();
  43. });
  44. // 执行调用
  45. $client->exec();
  46. $response->end('the result of rpc is ' . $rpcCallRet);
  47. });
  48. $http->start();

访问 http://localhost:9501/(示例请求地址) 即可看到结果为 the result of rpc is ModuleOne hello action

在 EasySwoole 中使用

  1. mainServerCreate 事件中注册 rpc 服务
  1. <?php
  2. namespace EasySwoole\EasySwoole;
  3. use EasySwoole\Component\Di;
  4. use EasySwoole\EasySwoole\AbstractInterface\Event;
  5. use EasySwoole\EasySwoole\Swoole\EventRegister;
  6. class EasySwooleEvent implements Event
  7. {
  8. public static function initialize()
  9. {
  10. date_default_timezone_set('Asia/Shanghai');
  11. }
  12. public static function mainServerCreate(EventRegister $register)
  13. {
  14. ###### 注册 rpc 服务 ######
  15. /** rpc 服务端配置 */
  16. // 构造方法内用户可传入节点管理器实现`NodeManagerInterface` 默认`MemoryManager`
  17. $config = new \EasySwoole\Rpc\Config();
  18. // 设置服务名称
  19. $config->setServerName('EasySwoole'); // 默认 EasySwoole
  20. // 【可选操作】设置节点id,可忽略,构造函数已经设置
  21. # $config->setNodeId(\EasySwoole\Utility\Random::character(10));
  22. // 设置异常处理器 对Service-Worker 和 AssistWorker的异常进行处理 必须设置 防止未捕获导致进程退出
  23. $config->setOnException(function (\Throwable $throwable) {
  24. });
  25. $serverConfig = $config->getServer();
  26. // 设置本机ip 必须设置
  27. $serverConfig->setServerIp('127.0.0.1');
  28. // 【可选操作】设置工作进程数量,默认为 4
  29. # $serverConfig->setWorkerNum(4);
  30. // 【可选操作】设置监听地址及端口,监听地址默认为 '0.0.0.0',端口默认为 9600
  31. # $serverConfig->setListenAddress('0.0.0.0');
  32. # $serverConfig->setListenPort('9600');
  33. // 【可选操作】设置服务端最大接受包大小,默认为 1024 * 1024 * 2 (即2M)
  34. # $serverConfig->setMaxPackageSize(1024 * 1024 * 2);
  35. // 【可选操作】设置接收客户端数据时间,默认为 3s
  36. # $serverConfig->setNetworkReadTimeout(3);
  37. /** 配置 rpc */
  38. $rpc = new \EasySwoole\Rpc\Rpc($config);
  39. // 创建 ServiceOne 服务
  40. $service = new \App\RpcServices\ServiceOne();
  41. // 添加 ModuleOne 模块到 ServiceOne 服务中
  42. $service->addModule(new \App\RpcServices\ModuleOne());
  43. // 添加 ServiceOne 服务到服务管理器中
  44. $rpc->serviceManager()->addService($service);
  45. // 注册 rpc 服务
  46. $rpc->attachServer(ServerManager::getInstance()->getSwooleServer());
  47. // 使用 \EasySwoole\Components\Di 组件保存 rpc 服务端注册服务完成后的实例,方便在框架的其他任何地方进行调用。
  48. Di::getInstance()->set('rpc', $rpc);
  49. }
  50. }
  1. 在控制器中进行服务调用
  1. <?php
  2. namespace App\HttpController;
  3. use EasySwoole\Component\Di;
  4. use EasySwoole\Http\AbstractInterface\Controller;
  5. use EasySwoole\Rpc\Protocol\Response;
  6. use EasySwoole\Rpc\Rpc;
  7. class Index extends Controller
  8. {
  9. /** @var Rpc */
  10. protected $rpcService;
  11. protected function onRequest(?string $action): ?bool
  12. {
  13. $this->rpcService = Di::getInstance()->get('rpc');
  14. return parent::onRequest($action);
  15. }
  16. public function index()
  17. {
  18. // 客户端调用
  19. $client = $this->rpcService->client();
  20. // 添加请求(调用 ServiceOne 服务的 ModuleOne 模块的 action 方法)
  21. $ctx2 = $client->addRequest('ServiceOne.ModuleOne.action');
  22. // 设置请求参数
  23. $ctx2->setArg('xxx');
  24. $rpcCallRet = '';
  25. // 设置调用成功执行回调
  26. $ctx2->setOnSuccess(function (Response $response) use (&$rpcCallRet) {
  27. // 调用成功获得响应
  28. var_dump($response->getMsg());
  29. $rpcCallRet = $response->getMsg();
  30. });
  31. // 设置调用失败执行回调
  32. $ctx2->setOnFail(function (Response $response) use (&$rpcCallRet) {
  33. // 调用失败获得响应
  34. var_dump($response->getMsg());
  35. $rpcCallRet = $response->getMsg();
  36. });
  37. // 执行调用
  38. $client->exec();
  39. $this->response()->write('the result of rpc is ' . $rpcCallRet);
  40. }
  41. }

访问 http://localhost:9501/(示例请求地址) 即可看到结果为 the result of rpc is ModuleOne hello action