使用Hyperf框架搭建jsonrpc服务

一、开发项目划分与搭建

JSON RPC 是一种基于 JSON 格式的轻量级的 RPC 协议标准,易于使用和阅读。在 Hyperf 里由 hyperf/json-rpc 组件来实现,可自定义基于 HTTP 协议来传输,或直接基于 TCP 协议来传输。

本次我选择使用基于 TCP 协议的 jsonrpc 协议来搭建服务。

服务有两种角色,一种是 服务提供者(ServiceProvider),即为其它服务提供服务的服务,另一种是 服务消费者(ServiceConsumer),即依赖其它服务的服务,一个服务既可能是 服务提供者(ServiceProvider),同时又是 服务消费者(ServiceConsumer)。而两者直接可以通过 服务契约 来定义和约束接口的调用,在 Hyperf 里,可直接理解为就是一个 接口类(Interface),通常来说这个接口类会同时出现在提供者和消费者下。

本次我搭建了一个服务提供者 calculate,为其他服务提供计算功能;一个消费者,通过 jsonrpc 协议调用 calculate 提供的计算功能。搭建过程如下:

1、搭建 calculate 服务提供者

  1. composer create-project hyperf/hyperf-skeleton calculate
  2. Which RPC protocol do you want to use ?
  3. [1] JSON-RPC with Service Governance
  4. [2] JSON-RPC
  5. [3] gRPC
  6. [n] None of the above
  7. Make your selection or type a composer package name and version (n): 2
  8. Which config center do you want to use ?
  9. [1] Apollo
  10. [2] Aliyun ACM
  11. [n] None of the above
  12. Make your selection or type a composer package name and version (n): 1
  13. Do you want to use hyperf/constants component ?
  14. [1] yes
  15. [n] None of the above
  16. Make your selection (n): 1
  17. Do you want to use hyperf/async-queue component ? (A simple redis queue component)
  18. [1] yes
  19. [n] None of the above
  20. Make your selection or type a composer package name and version (n): 1
  21. Do you want to use hyperf/amqp component ?
  22. [1] yes
  23. [n] None of the above
  24. Make your selection or type a composer package name and version (n): 1
  25. Do you want to use hyperf/model-cache component ?
  26. [1] yes
  27. [n] None of the above
  28. Make your selection or type a composer package name and version (n): 1
  29. Do you want to use hyperf/elasticsearch component ?
  30. [1] yes
  31. [n] None of the above
  32. Make your selection or type a composer package name and version (n): n
  33. Do you want to use hyperf/tracer component ? (A open tracing protocol component, adapte with Zipkin etc.)
  34. [1] yes
  35. [n] None of the above
  36. Make your selection or type a composer package name and version (n): 1

2、搭建 gateway 服务消费者

  1. composer create-project hyperf/hyperf-skeleton gateway
  2. Which RPC protocol do you want to use ?
  3. [1] JSON-RPC with Service Governance
  4. [2] JSON-RPC
  5. [3] gRPC
  6. [n] None of the above
  7. Make your selection or type a composer package name and version (n): 2
  8. Which config center do you want to use ?
  9. [1] Apollo
  10. [2] Aliyun ACM
  11. [n] None of the above
  12. Make your selection or type a composer package name and version (n): 1
  13. Do you want to use hyperf/constants component ?
  14. [1] yes
  15. [n] None of the above
  16. Make your selection (n): 1
  17. Do you want to use hyperf/async-queue component ? (A simple redis queue component)
  18. [1] yes
  19. [n] None of the above
  20. Make your selection or type a composer package name and version (n): 1
  21. Do you want to use hyperf/amqp component ?
  22. [1] yes
  23. [n] None of the above
  24. Make your selection or type a composer package name and version (n): 1
  25. Do you want to use hyperf/model-cache component ?
  26. [1] yes
  27. [n] None of the above
  28. Make your selection or type a composer package name and version (n): 1
  29. Do you want to use hyperf/elasticsearch component ?
  30. [1] yes
  31. [n] None of the above
  32. Make your selection or type a composer package name and version (n): n
  33. Do you want to use hyperf/tracer component ? (A open tracing protocol component, adapte with Zipkin etc.)
  34. [1] yes
  35. [n] None of the above
  36. Make your selection or type a composer package name and version (n): 1

二、JSON RPC服务开发与配置

1、calculate 功能开发

app 目录结构

  1. app
  2. Constants
  3. Controller
  4. Exception
  5. JsonRpc
  6. CalculatorService.php
  7. CalculatorServiceInterface.php
  8. Listener
  9. Model
  10. Process

app\JsonRpc\CalculatorService.php

  1. <?php
  2. namespace App\JsonRpc;
  3. use Hyperf\RpcServer\Annotation\RpcService;
  4. /**
  5. * Class CalculatorService
  6. * @RpcService(name="CalculatorService", protocol="jsonrpc", server="jsonrpc")
  7. */
  8. class CalculatorService implements CalculatorServiceInterface
  9. {
  10. public function add(int $v1, int $v2): int
  11. {
  12. return $v1 + $v2;
  13. }
  14. }

app\JsonRpc\CalculatorServiceInterface.php

  1. <?php
  2. declare(strict_types=1);
  3. namespace App\JsonRpc;
  4. interface CalculatorServiceInterface
  5. {
  6. public function add(int $v1, int $v2): int;
  7. }

calculate 服务配置
config\autoload\server.php

  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of Hyperf.
  5. *
  6. * @link https://www.hyperf.io
  7. * @document https://doc.hyperf.io
  8. * @contact group@hyperf.io
  9. * @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
  10. */
  11. use Hyperf\Server\Server;
  12. use Hyperf\Server\SwooleEvent;
  13. return [
  14. 'mode' => SWOOLE_PROCESS,
  15. 'servers' => [
  16. [
  17. 'name' => 'jsonrpc',
  18. 'type' => Server::SERVER_BASE,
  19. 'host' => '0.0.0.0',
  20. 'port' => 9501,
  21. 'sock_type' => SWOOLE_SOCK_TCP,
  22. 'callbacks' => [
  23. SwooleEvent::ON_RECEIVE => [Hyperf\JsonRpc\TcpServer::class, 'onReceive'],
  24. ],
  25. 'settings' => [
  26. 'open_eof_split' => true,
  27. 'package_eof' => "\r\n",
  28. ]
  29. ],
  30. ],
  31. 'settings' => [
  32. 'enable_coroutine' => true,
  33. 'worker_num' => swoole_cpu_num(),
  34. 'pid_file' => BASE_PATH . '/runtime/hyperf.pid',
  35. 'open_tcp_nodelay' => true,
  36. 'max_coroutine' => 100000,
  37. 'open_http2_protocol' => true,
  38. 'max_request' => 100000,
  39. 'socket_buffer_size' => 2 * 1024 * 1024,
  40. ],
  41. 'callbacks' => [
  42. SwooleEvent::ON_BEFORE_START => [Hyperf\Framework\Bootstrap\ServerStartCallback::class, 'beforeStart'],
  43. SwooleEvent::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
  44. SwooleEvent::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
  45. ],
  46. ];

2、gateway 消费者功能开发

app 目录结构

  1. app
  2. Constants
  3. Controller
  4. IndexController.php
  5. Exception
  6. JsonRpc
  7. CalculatorServiceInterface.php
  8. Listener
  9. Model
  10. Process

app\JsonRpc\CalculatorServiceInterface.php

  1. <?php
  2. declare(strict_types=1);
  3. namespace App\JsonRpc;
  4. interface CalculatorServiceInterface
  5. {
  6. public function add(int $v1, int $v2): int;
  7. }

config\routes.php

  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of Hyperf.
  5. *
  6. * @link https://www.hyperf.io
  7. * @document https://doc.hyperf.io
  8. * @contact group@hyperf.io
  9. * @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
  10. */
  11. use Hyperf\HttpServer\Router\Router;
  12. Router::addRoute(['GET', 'POST', 'HEAD'], '/', 'App\Controller\IndexController@index');
  13. Router::get('/add', 'App\Controller\IndexController@add');

app\Controller\IndexController.php

  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of Hyperf.
  5. *
  6. * @link https://www.hyperf.io
  7. * @document https://doc.hyperf.io
  8. * @contact group@hyperf.io
  9. * @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
  10. */
  11. namespace App\Controller;
  12. use Hyperf\Utils\Context;
  13. use Hyperf\Utils\Coroutine;
  14. use Hyperf\Utils\Parallel;
  15. use Hyperf\Utils\ApplicationContext;
  16. use App\JsonRpc\CalculatorServiceInterface;
  17. use App\JsonRpc\MathValue;
  18. class IndexController extends AbstractController
  19. {
  20. public function index()
  21. {
  22. $user = $this->request->input('user', 'Hyperf');
  23. $method = $this->request->getMethod();
  24. return [
  25. 'method' => $method,
  26. 'message' => "Hello {$user}.",
  27. ];
  28. }
  29. public function add()
  30. {
  31. $client = ApplicationContext::getContainer()->get(CalculatorServiceInterface::class);
  32. $value = $client->add(10, 20);
  33. return $value;
  34. }
  35. }

gateway 服务配置
config\autoload\server.php

  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of Hyperf.
  5. *
  6. * @link https://www.hyperf.io
  7. * @document https://doc.hyperf.io
  8. * @contact group@hyperf.io
  9. * @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
  10. */
  11. use Hyperf\Server\Server;
  12. use Hyperf\Server\SwooleEvent;
  13. return [
  14. 'mode' => SWOOLE_PROCESS,
  15. 'servers' => [
  16. [
  17. 'name' => 'http',
  18. 'type' => Server::SERVER_HTTP,
  19. 'host' => '0.0.0.0',
  20. 'port' => 9500,
  21. 'sock_type' => SWOOLE_SOCK_TCP,
  22. 'callbacks' => [
  23. SwooleEvent::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],
  24. ],
  25. ],
  26. ],
  27. 'settings' => [
  28. 'enable_coroutine' => true,
  29. 'worker_num' => swoole_cpu_num(),
  30. 'pid_file' => BASE_PATH . '/runtime/hyperf.pid',
  31. 'open_tcp_nodelay' => true,
  32. 'max_coroutine' => 100000,
  33. 'open_http2_protocol' => true,
  34. 'max_request' => 100000,
  35. 'socket_buffer_size' => 2 * 1024 * 1024,
  36. ],
  37. 'callbacks' => [
  38. SwooleEvent::ON_BEFORE_START => [Hyperf\Framework\Bootstrap\ServerStartCallback::class, 'beforeStart'],
  39. SwooleEvent::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
  40. SwooleEvent::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
  41. ],
  42. ];

config\autoload\services.php

  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of Hyperf.
  5. *
  6. * @link https://www.hyperf.io
  7. * @document https://doc.hyperf.io
  8. * @contact group@hyperf.io
  9. * @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
  10. */
  11. return [
  12. 'consumers' => [
  13. [
  14. // name 需与服务提供者的 name 属性相同
  15. 'name' => 'CalculatorService',
  16. // 服务接口名,可选,默认值等于 name 配置的值,如果 name 直接定义为接口类则可忽略此行配置,如 name 为字符串则需要配置 service 对应到接口类
  17. 'service' => \App\JsonRpc\CalculatorServiceInterface::class,
  18. // 对应容器对象 ID,可选,默认值等于 service 配置的值,用来定义依赖注入的 key
  19. 'id' => \App\JsonRpc\CalculatorServiceInterface::class,
  20. // 服务提供者的服务协议,可选,默认值为 jsonrpc-http
  21. 'protocol' => 'jsonrpc',
  22. // 负载均衡算法,可选,默认值为 random
  23. 'load_balancer' => 'random',
  24. // 这个消费者要从哪个服务中心获取节点信息,如不配置则不会从服务中心获取节点信息
  25. // 'registry' => [
  26. // 'protocol' => 'consul',
  27. // 'address' => 'http://127.0.0.1:8500',
  28. // ],
  29. // 如果没有指定上面的 registry 配置,即为直接对指定的节点进行消费,通过下面的 nodes 参数来配置服务提供者的节点信息
  30. 'nodes' => [
  31. ['host' => '127.0.0.1', 'port' => 9501],
  32. ],
  33. ]
  34. ],
  35. ];

三、服务启动与通信演示

1、启动 calculate 服务

  1. root@cosyphp-VirtualBox:~# cd /home/wwwroot/calculate/
  2. root@cosyphp-VirtualBox:/home/wwwroot/calculate# php bin/hyperf.php start

2、启动 gateway 服务

  1. root@cosyphp-VirtualBox:~# cd /home/wwwroot/gateway/
  2. root@cosyphp-VirtualBox:/home/wwwroot/gateway# php bin/hyperf.php start

3、请求 gateway 服务

  1. root@cosyphp-VirtualBox:~# curl http://127.0.0.1:9500/add
  2. 30
  3. root@cosyphp-VirtualBox:~#

四、各服务关系总览

各服务关系



评论 0

发表评论

Top