您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
gRPC实现(hyperf与postman交互)
发布时间:2022-10-08 21:51:04编辑:雪饮阅读()
环境:
Hyperf2.2.35
Swoole4.8.5(编译时必须开启--enable-http2,否则postman无法通行,内置客户端应该也是,并且没有明显的报错)
Php7.4
Postman版本:Version 10.0.19(较新postman支持grpc请求)
定义好 proto 文件 grpc.proto
syntax = "proto3";
package grpc;
service hi {
rpc sayHello (HiUser) returns (HiReply) {
}
}
message HiUser {
string name = 1;
int32 sex = 2;
}
message HiReply {
string message = 1;
HiUser user = 2;
}
使用 protoc 生成示例代码
protoc不同Linux发行版未必内置,需要自行安装
tar -zxvf protobuf-all-21.7.tar.gz
cd protobuf-21.7/
ls
./configure --prefix=/usr/local/protobuf217
make && make install
[root@localhost hyperf-skeleton]# which protoc
/usr/local/protobuf217/bin/protoc
# 使用 protoc 自动生成代码
protoc --php_out=grpc/ grpc.proto
# tree grpc
grpc
├── GPBMetadata
│ └── Grpc.php
└── Grpc
├── HiReply.php
└── HiUser.php
配置 composer.json, 使用 grpc/ 下代码的自动加载. 如果 proto 文件中使用不同的 package 设置, 或者使用了不同的目录, 进行相应调整即可,添加之后执行 composer dump-autoload 使自动加载生效
"autoload": {
"psr-4": {
"App\\": "app/",
"GPBMetadata\\": "grpc/GPBMetadata",
"Grpc\\": "grpc/Grpc"
},
"files": [
]
},
安装组件
composer require hyperf/grpc-server
gRPC server 服务器配置
server.php 文件(参考 配置):
'servers' => [
....
[
'name' => 'grpc',
'type' => Server::SERVER_HTTP,
'host' => '0.0.0.0',
'port' => 9503,
'sock_type' => SWOOLE_SOCK_TCP,
'callbacks' => [
Event::ON_REQUEST => [\Hyperf\GrpcServer\Server::class, 'onRequest'],
],
],
],
gRPC server 路由配置
routes.php 文件(参考 路由):
Router::addServer('grpc', function () {
Router::addGroup('/grpc.hi', function () {
Router::post('/sayHello', 'App\Controller\HiController@sayHello');
});
});
HiController.php 文件中的 sayHello 方法:
public function sayHello(HiUser $user)
{
$message = new HiReply();
$message->setMessage("Hello World");
$message->setUser($user);
return $message;
}
启动服务:
[root@localhost hyperf-skeleton]# /www/server/php/74/bin/php -c /www/server/php/74/etc/php.ini bin/hyperf.php start
Postman建立grpc请求
在postman的API Network下面有个new=》Create New=>gRPC Request
在新建的Untitled gRPC Request的Select a method的地方下拉,有Import a .proto file和Use server reflection,前者是从本地导入.proto文件,后者则是直接从gRPC服务端发现方法的定义。
这里自动发现服务端的定义,暂时会报错,可能是hyperf框架本身bug,
定义文件(.proto后缀的文件)一般的同服务端从c++代码生成为php代码时候的示例定义文件相同
grpc.proto:
syntax = "proto3";
package grpc;
service hi {
rpc sayHello (HiUser) returns (HiReply) {
}
}
message HiUser {
string name = 1;
int32 sex = 2;
}
message HiReply {
string message = 1;
HiUser user = 2;
}
导入后在Import as API里面选择一个API,要导入到目标API中,等下就可以从Select a method下拉的地方选择这个API,然后读取这个API里面的proto的定义方法了。
如果之前没有API,可以先建立API,在postman左侧APIs=》+后输入一个API名称(有默认名称就是“New API”)就可以建立一个API
然后就可以选择proto文件导入到该API了,然后就可以从Select a method下拉的地方选择这个API,然后读取这个API里面的proto的定义方法了。
点击Untitled gRPC Request最右侧的invoke就可以发生grpc消息了
当然这样发送的是空的消息体
点击Untitled gRPC Request下面的Message选项卡下面的Generate Example Message可以根据当前导入的proto文件里面的定义结构产生一个模拟的消息体如:
再次invoke,就是模拟的正常的grpc通讯了,通信成功后在下面的Response选项卡中会响应内容如:
注意:
如果HiController控制器没有显式定义空参构造
则会产生grpc客户端接收到空的响应结果
HiController应包含显式空参构造,如:
<?php
namespace App\Controller;
use Hyperf\GrpcClient\BaseClient;
use Grpc\HiUser;
use Grpc\HiReply;
class HiController extends BaseClient
{
public function __construct()
{
}
public function sayHello(HiUser $user)
{
$message = new HiReply();
$message->setMessage("Hello World");
$message->setUser($user);
return $message;
}
}
这可能是hyperf的某种实现机制导致,案例来说继承父类,则隐式的空参构造应该会自动调用父级的。
关键字词:gRPC,实现,hyperf,postman,交互