Hyperf JSON RPC 服务 Demo_Dom_留声机的博客-程序员宅基地

技术标签: Hyperf  微服务  原创  JSON RPC  php  

系列文章目录

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


提示:以下例子使用TCP服务,例子经过作者验证


前言

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

提示:推荐使用docker容器进行实验,毕竟模拟分布式可以更加直观


一、使用搭建环境

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

  1. 搭建 hyperf_server 服务提供者
# composer 下载全新的hyperf
composer create-project hyperf/hyperf-skeleton hyperf_server

## composer 安装相关需要的扩展
composer require hyperf/json-rpc
composer require hyperf/service-governance # consul 服务中心扩展
composer require hyperf/rpc-server # JSON RPC 服务端
  1. 搭建hyperf_client服务消费者
# composer 下载全新的hyperf
composer create-project hyperf/hyperf-skeleton hyperf_client

## composer 安装相关需要的扩展
composer require hyperf/json-rpc
composer require hyperf/service-governance # consul 服务中心扩展
composer require hyperf/rpc-client # JSON RPC 服务端

二、JSON RPC 服务提供者 功能开发与配置

  1. hyperf_server功能开发
    app 目录结构
app
    Constants
    Controller
    Exception
    JsonRpc *
        CalculatorService.php *
        CalculatorServiceInterface.php *
    Listener
    Model
    Process

app\JsonRpc\CalculatorService.php

<?php
namespace App\JsonRpc;
use Hyperf\RpcServer\Annotation\RpcService;
/**
 * 注意,如希望通过服务中心来管理服务,需在注解内增加 publishTo 属性
 * @RpcService(name="CalculatorService", protocol="jsonrpc", server="jsonrpc", publishTo="consul")
 */
class CalculatorService implements CalculatorServiceInterface
{
    
    public function sum(int $v1, int $v2): int
    {
    
        return $v1 + $v2;
    }
}

app\JsonRpc\CalculatorServiceInterface.php

<?php
namespace App\JsonRpc;
/**
 * Class CalculatorService
 * @package App\JsonRpc
 */
interface CalculatorServiceInterface
{
    
    public function sum(int $a, int $b): int;
}
  1. hyperf_server 服务配置
    config\autoload\server.php
<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  [email protected]
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
use Hyperf\Server\Server;
use Hyperf\Server\SwooleEvent;

return [
    'mode' => SWOOLE_PROCESS,
    'servers' => [
//        [
//            'name' => 'http',
//            'type' => Server::SERVER_HTTP,
//            'host' => '0.0.0.0',
//            'port' => 9501,
//            'sock_type' => SWOOLE_SOCK_TCP,
//            'callbacks' => [
//                SwooleEvent::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],
//            ],
//        ],
        [
        	// 这里是HTTP通讯形式
            'name' => 'jsonrpc-http',
            'type' => Server::SERVER_HTTP,
            'host' => '0.0.0.0',
            'port' => 9504,
            'sock_type' => SWOOLE_SOCK_TCP,
            'callbacks' => [
                SwooleEvent::ON_REQUEST => [\Hyperf\JsonRpc\HttpServer::class, 'onRequest'],
            ],
        ],
        [
        	// 这里是TCP通讯形式
            'name' => 'jsonrpc',
            'type' => Server::SERVER_BASE,
            'host' => '0.0.0.0',
            'port' => 9501,
            'sock_type' => SWOOLE_SOCK_TCP,
            'callbacks' => [
                SwooleEvent::ON_RECEIVE => [\Hyperf\JsonRpc\TcpServer::class, 'onReceive'],
            ],
            'settings' => [
                'open_eof_split' => true,
                'package_eof' => "\r\n",
            ],
        ],
    ],
    'settings' => [
        'enable_coroutine' => true,
        'worker_num' => swoole_cpu_num(),
        'pid_file' => BASE_PATH . '/runtime/hyperf.pid',
        'open_tcp_nodelay' => true,
        'max_coroutine' => 100000,
        'open_http2_protocol' => true,
        'max_request' => 100000,
        'socket_buffer_size' => 2 * 1024 * 1024,
        'buffer_output_size' => 2 * 1024 * 1024,
    ],
    'callbacks' => [
        SwooleEvent::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
        SwooleEvent::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
        SwooleEvent::ON_WORKER_EXIT => [Hyperf\Framework\Bootstrap\WorkerExitCallback::class, 'onWorkerExit'],
    ],
];

三、JSON RPC 服务消费者 功能开发与配置

  1. hyperf_client功能开发
    app 目录结构
app
    Constants
    Controller *
        IndexController.php *
    Exception
    JsonRpc *
        CalculatorServiceInterface.php *
    Listener
    Model
    Process

app\JsonRpc\CalculatorServiceInterface.php

<?php
declare(strict_types=1);
namespace App\JsonRpc;
interface CalculatorServiceInterface
{
    
    public function sum(int $v1, int $v2): int;
}

app\Controller\IndexController.php

<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  [email protected]
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Controller;

use App\JsonRpc\CalculatorServiceInterface;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Di\Annotation\Inject;

/**
 * @Controller()
 * Class IndexController
 * @package App\Controller
 */
class IndexController extends AbstractController
{
    
    /**
     * @GetMapping(path="sum")
     * @return int
     */
    public function sum()
    {
    
        $client = ApplicationContext::getContainer()->get(CalculatorServiceInterface::class);
        $value = $client->sum(1, 2);
        return $value;
    }
	/**
     * //在这里我们注入了一个接口类,并直接调用接口的sum方法,但在本项目并没有add
    方法的实现,真正的add方法在服务提供者里已经实现了,hyperf会帮我们找到相应服务并使用
     * @Inject()
     * @var CalculatorServiceInterface
     */
    private $calculatorService;
    /**
     * @GetMapping(path="sum2")
     * @return int
     */
    public function sum2(){
    
        return $this->calculatorService->sum(1,2);
    }
}
  1. hyperf_client 服务配置
    config\autoload\server.php
<?php
declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://doc.hyperf.io
 * @contact  [email protected]
 * @license  https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
 */
use Hyperf\Server\Server;
use Hyperf\Server\SwooleEvent;
return [
    'mode' => SWOOLE_PROCESS,
    'servers' => [
        [
            'name' => 'http',
            'type' => Server::SERVER_HTTP,
            'host' => '0.0.0.0',
            'port' => 9500, // 修改http端口 免得端口占用
            'sock_type' => SWOOLE_SOCK_TCP,
            'callbacks' => [
                SwooleEvent::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],
            ],
        ],
    ],
    'settings' => [
        'enable_coroutine' => true,
        'worker_num' => swoole_cpu_num(),
        'pid_file' => BASE_PATH . '/runtime/hyperf.pid',
        'open_tcp_nodelay' => true,
        'max_coroutine' => 100000,
        'open_http2_protocol' => true,
        'max_request' => 100000,
        'socket_buffer_size' => 2 * 1024 * 1024,
    ],
    'callbacks' => [
        SwooleEvent::ON_BEFORE_START => [Hyperf\Framework\Bootstrap\ServerStartCallback::class, 'beforeStart'],
        SwooleEvent::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
        SwooleEvent::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
    ],
];

config\autoload\services.php
没有这个配置文件则新建

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

四、服务启动与通信演示

  1. 启动 consul 服务中心
consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -node=Dome -bind=127.0.0.1 -ui -client=0.0.0.0
  1. 启动 hyperf_client 服务
php hyperf_client/bin/hyperf.php start
  1. 启动 hyperf_server 服务
php hyperf_server/bin/hyperf.php start
  1. 通信演示
curl http://127.0.0.1:9500/sum
# 返回3 则正确
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_14824885/article/details/111252718

智能推荐

CentOS下mysql数据库常用命令总结-程序员宅基地

CentOS下mysql数据库常用命令总结mysql数据库使用总结本文主要记录一些mysql日常使用的命令,供以后查询。1.更改root密码mysqladmin -uroot password 'yourpassword'2.远程登陆mysql服务器mysql -uroot -p -h192.168.137.10 -P33063.查询数据库...

Dell EMC PowerEdge 配置 iDRAC_dell poweredge http管理界面-程序员宅基地

打开受管理的系统。 在开机自检(POST)过程中按。 在系统设置主菜单页面中,单击iDRAC Settings(iDRAC设置)。随即显示iDRAC Settings(iDRAC设置)页面。 单击"Network(网络)"。随即显示Networking(网络)页面。 指定网络设置。在"Enable NIC"(启用NIC)下面,选择Enabled(启用)。-Shared LOM(共享LOM)(1、2、3或4)将共享主板上的其中一个NIC -Dedicate..._dell poweredge http管理界面

7-1 实验10_9_指针数组进阶 (100 分)_从键盘上输入n个字符串(每个字符串的长度小于20,字符串包含空白字符),对其进行升_ChaoYue_miku的博客-程序员宅基地

7-1 实验10_9_指针数组进阶 (100 分)已知正整数n,n的范围是1—100。你要从键盘读入n个字符串,每个字符串的长度不确定,但是n个字符串的总长度不超过100000。你要利用字符指针数组将这n个字符串按照ASCII码顺序进行升序排序,然后再打印到屏幕上。字符串中可能包含ASCII码中的任意字符,每个字符串以换行符结束输入。要求:不允许定义如char str[100][100000];这样的二维数组,因为会极大的浪费内存空间。你应定义char str[100000];这样的存储空间,将n个字符_从键盘上输入n个字符串(每个字符串的长度小于20,字符串包含空白字符),对其进行升

由于不能验证所收到的数据是否可信,无法显示您想要查看的页面。建议向此网站的管理员反馈这个问题。_由于不能验证所收到的数据是否可信,无法显示您想要查看的页面。 建议向此网站的管_都什么什么啊的博客-程序员宅基地

代理服务器的问题https://tieba.baidu.com/p/5771890231但是有些网站还是打不开啊_由于不能验证所收到的数据是否可信,无法显示您想要查看的页面。 建议向此网站的管

使用Mybatis/TkMybatis/Mybatis-Plus框架报错:无效的列类型: 1111_mybatis-plus 写入oracle报错1111-程序员宅基地

使用Mybatis/TkMybatis/Mybatis-Plus框架报错:无效的列类型: 1111_mybatis-plus 写入oracle报错1111

python与openssl 进行rsa签名与验证_crypto库生成的签名值要经过反序后才能由openssl库进行验证-程序员宅基地

1、Python生成RSA秘钥,与签名验证# rsa签名,保存私钥公钥到本地from cryptography.hazmat.primitives.asymmetric import paddingfrom cryptography.hazmat.primitives import hashesfrom cryptography.hazmat.primitives import serializationfrom OpenSSL import cryptorsa_key = crypto.r_crypto库生成的签名值要经过反序后才能由openssl库进行验证

随便推点

【Java8新特性】Optional类-程序员宅基地

文章目录1 概述2 Optional类的方法3 总结参考资料1 概述到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类, Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到GoogleGuava的启发,Optional类已经成为Java8类库的一部分。Optional<T>类(java.util.Optional) 是一个容器类,它可以保存类型T的值,

Oracle AWR报告详细分析--比较详细-程序员宅基地

https://blog.csdn.net/demonson/article/details/79474133转载于:https://www.cnblogs.com/ritchy/p/10460984.html_oracle awr最好多长

Windows10在线安装Selenium遇到的问题(超时和没有权限)_selenium wos you don't have permission-程序员宅基地

Windows10在线安装Selenium遇到的问题(超时和没有权限)1.安装时出现超时2.安装时提示没有权限具体遇到问题的解决方案:1.在cmd进入命令行:pip install selenium,结果提示安装失败排查:原因是因为超时解决方案:因为超时了,所以加上超时时间。命令行:pip --default-timeout=150 install selenium..._selenium wos you don't have permission

google搜索的使用-程序员宅基地

你真的会使用google么? 如今遇到问题都会在搜索引擎中寻找答案,如何快速准确的寻找出你xiang

蓝桥试题 算法提高 字母大小写转换 JAVA-程序员宅基地

问题描述  从键盘输入一个字符,如果是大写字母(A-Z),就转换成小写;如果是小写字母(a-z),就转换成大写,如果是其他字符原样保持并将结果输出。输入格式  输入一行,包含一个字符。输出格式  输出一行,即按照要求输出的字符。样例输入a样例输出A思路:直接转成字符数组,然后利用ASCII码值,就可,结果千算万算没算出来这个居然还要求了 @ ( * . ?这几个字符,然后我的代...

JavaScript小练习4-鼠标移入移出改变样式_网购界面鼠标移入变化 条件渲染 js-程序员宅基地

题目移出:移入:分析思路清晰,onmouseover和onmouseout的使用,注意的地方有:width和height设置的是content的内容,padding和border要注意设置,实现前后大小相同,就要让整个盒子大小一致,即border也进行设置。cssText设置内联样式,cssText=""可清空内联样式。之前没明白onload的作用,这次理解了,之前onload..._网购界面鼠标移入变化 条件渲染 js