hyperf下使用gRPC实现接口调用

依赖扩展

php扩展

  • swoole扩展
  • gRPC扩展
  • curl
  • openssl

系统扩展

  • protoc
  • gRPC 生成相关语言代码插件

安装Hyperf框架

1
composer create-project hyperf/hyperf-skeleton 

安装过程中需要指定要安装 gRPC 扩展包,http2等,因为 gRPC 是在http2的基础上构建的

安装完成后配置 gRPC 服务

在config/autoload/server.php 中添加 gRPC 配置

1
2
3
4
5
6
7
8
9
10
[
'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'],
],
],

配置路由

在config/routes.php配置 gRPC 路由,路由规则 .proto 文件中的定义和 gRPC server 路由的对应关系: /{package}.{service}/{rpc}

1
2
3
4
5
Router::addServer('grpc', function () {
Router::addGroup('/grpc.hi', function () {
Router::post('/sayHello', 'App\Controller\HiController@sayHello');
});
});

启动服务

1
php bin/hyperf.php start

查看 gRPC 服务中配置的端口是否启动,如果启动成功,gRPC 服务已经搭建完成,如果启动失败,请重新检查哪个步骤是否遗漏

生成gRPC php相关代码

  1. 新建 demo.proto 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;
}
  1. protoc –php_out=grpc demo.proto
  2. 配置自动加载

我在hyperf根目录下创建了grpc目录

1
2
"GPBMetadata\\": "grpc/GPBMetadata",
"Grpc\\": "grpc/Grpc"
  1. 添加 gRPC Server 端代码

新建HiController.php文件,并添加 sayHello 方法

1
2
3
4
5
6
7
public function sayHello(HiUser $user) 
{
$message = new HiReply();
$message->setMessage("Hello World");
$message->setUser($user);
return $message;
}
  1. 实现 gRPC Client 端代码

hyperf 已经封装好了 \Hyperf\GrpcClient\BaseClient, 只要根据 .proto 文件中的定义, 按需扩展:

1
2
3
4
5
6
7
8
public function sayHello(HiUser $argument)
{
return $this->_simpleRequest(
'/grpc.hi/sayHello',
$argument,
[HiReply::class, 'decode']
);
}
  1. 在其他随意一个控制器中调用 client 代码,并输出到页面上
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public function index()
{
$client = new HiClient('127.0.0.1:9503', [
'credentials' => null,
]);
$request = new HiUser();
$request->setName('hyperf');
$request->setSex(1);
/**
* @var \Grpc\HiReply $reply
*/
list($reply, $status) = $client->sayHello($request);

$message = $reply->getMessage();
$user = $reply->getUser();

var_dump($message);
var_dump($user->getName());

return $this->response->json(['message'=>$message,'name' => $user?->getName()]);
}
  1. 请求 index ,查看输出结果
1
{"message":"Hello gRPC","name":"hyperf"}