紧接上一篇,下面用PHP
作为客户端调用Go
的服务端。
安装 grpc_php_plugin 插件
grpc_php_plugin
插件可以帮助我们自动生成client stub
客户端(封装了grpc
的服务接口),方便我们直接引入调用,否则只生成服务/请求/响应的实体类,用起来不太方便。
# 下载 grpc 的库到本地
cd ~ && git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
# 更新子模块依赖
cd grpc && git submodule update --init
# 这里我们只编译 php 的插件 如果要编译所有的 make && make install
make grpc_php_plugin
# 插件路径
ll ./bins/opt/grpc_php_plugin
生成PHP客户端
PHP
只能做C
端,且需要安装grpc
和protobuf
扩展和库。
###生成php客户端库
#不会有 client stub 类
protoc -I. --php_out=plugins=grpc:./user user.proto
# 会有 client stub 类
protoc -I. \
--php_out=./user \
--grpc_out=./user \
--plugin=protoc-gen-grpc=/root/grpc/bins/opt/grpc_php_plugin \
user.proto
# 查看生成的服务类库
[root@localhost grpc]# tree user
user
├── GPBMetadata
│ └── User.php
├── User
│ ├── UserClient.php
│ ├── UserDeleteRequest.php
│ ├── UserDeleteResponse.php
│ ├── UserEntity.php
│ ├── UserIndexRequest.php
│ ├── UserIndexResponse.php
│ ├── UserPostRequest.php
│ ├── UserPostResponse.php
│ ├── UserViewRequest.php
│ └── UserViewResponse.php
└── user.pb.go
PHP GRPC 扩展及依赖安装
#安装扩展
pecl install grpc
pecl install protobuf
使用 composer
管理依赖加载。
mkdir grpc-php-client && cd grpc-php-client
# 使用 composer 管理项目
composer init
# 安装 grpc/protobuf 的客户端库文件
composer require grpc/grpc
composer require google/protobuf
# 新建 grpc 服务库目录 将生成的PHP客户端文件移动至此
mkdir grpc && mv $GOPATH/src/grpc/user/* ./grpc
# 注册 psr4 自动加载服务的客户端文件
vi composer.json
{
"name": "root/php-client",
"require": {
"grpc/grpc": "^1.19",
"google/protobuf": "^3.7"
},
"autoload": {
"psr-4": {
"User\\": "./grpc/User/",
"GPBMetadata\\": "./grpc/GPBMetadata/"
}
}
}
# 更新 composer 加载器
composer dump-autoload
PHP客户端代码实例
在安装完php
的grpc
扩展和依赖库后,我们就可以编写代码了。
<?php
require_once __DIR__ . '/vendor/autoload.php';
use User\UserClient;
use User\UserEntity;
use User\UserIndexRequest;
use User\UserIndexResponse;
use User\UserViewRequest;
use User\UserViewResponse;
use User\UserPostRequest;
use User\UserPostResponse;
use User\UserDeleteRequest;
use User\UserDeleteResponse;
// 创建客户端实例
$userClient = new UserClient('10.10.31.211:50051', [
'credentials' => Grpc\ChannelCredentials::createInsecure()
]);
$userIndexRequest = new UserIndexRequest();
$userIndexRequest->setPage(1);
$userIndexRequest->setPageSize(12);
/* @var $userIndexResponse UserIndexResponse */
/* @var $statusObj stdClass */
list($userIndexResponse, $statusObj) = $userClient->UserIndex($userIndexRequest)->wait();
if (0 != $statusObj->code) {
throw new \Exception($statusObj->details, $statusObj->code);
}
printf("index request end: err %d msg %s" . PHP_EOL, $userIndexResponse->getErr(), $userIndexResponse->getMsg());
/* @var $data UserEntity[] */
$data = $userIndexResponse->getData();
foreach ($data as $row) {
echo $row->getName() . " " . $row->getAge() . PHP_EOL;
}
// 剩余的就不写了 都很简单的
// $userClient->UserView();
// $userClient->UserPost();
// $userClient->UserDelete();
# 结果
[root@localhost php-client]# php index.php
index request end: err 0 msg success
big_cat 28
sqrt_cat 29
Protobuf 的原生使用
grpc
使用protobuf
作为IDL
,声明服务接口,请求实体,响应实体,后续我们将自己业务填充进去,客户端发送请求实体,服务端服务接口处理业务,然后返回响应实体,请求/响应实体的数据传输也使用protobuf
进行了打包/解包。
# 打包
//\Google\Protobuf\Internal\Message::serializeToString
# 解包
//\Google\Protobuf\Internal\Message::mergeFromString
// 客户端
$message = new Message();
$message->setId(1);
$message->setName("sqrt_cat");
$message->setAddress("shanghai");
$package = $message->serializeToString();
// 发送 $package 至服务端
// 服务端接收数据后使用对应的实体解包
// 服务端
$message = new Message();
$message->mergeFromString($package);
var_dump($message->getId(), $message->getName(), $message->getAddress());
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。