gRPC 用于 PHP:库和实现示例
gRPC(gRPC 远程过程调用)是 Google 开发的高性能远程过程调用框架。它使用 Protocol Buffers(protobuf)作为接口定义语言和数据序列化格式。与 REST 不同,gRPC 基于 HTTP/2 运行,支持双向流传输,并提供强类型。在本文中,我们将介绍如何在 PHP 中集成 gRPC,使用哪些库,并编写一个完整的客户端-服务器交互示例。
PHP 中 gRPC 库概述
在 PHP 中使用 gRPC 有两种主要方法:
- grpc.so 扩展 — 来自 gRPC 的官方 C 扩展。提供最佳性能,但需要在服务器上进行编译和配置。
- 纯 PHP 客户端(例如,通过 Composer 的
grpc/grpc)— 基于 PHP 的实现,通过 cURL 和 HTTP/2 运行。速度较慢,但部署更简单。
对于生产环境,建议使用 grpc 扩展;对于开发或测试,建议使用纯 PHP 客户端。
安装必要组件
1. 安装 protoc 和 PHP 插件
从官方仓库下载适用于您操作系统的 protobuf 编译器。要生成 PHP 代码,需要 protoc-gen-php-grpc 插件:
# 安装 protoc (Linux)wget https://github.com/protocolbuffers/protobuf/releases/download/v25.0/protoc-25.0-linux-x86_64.zipunzip protoc-25.0-linux-x86_64.zip -d /usr/local/protocexport PATH=$PATH:/usr/local/protoc/bin
# 安装 gRPC PHP 插件sudo apt-get install php-dev php-cli php-pearsudo pecl install grpcsudo pecl install protobuf2. 安装 Composer 依赖
创建项目并添加必要的包:
composer initcomposer require grpc/grpccomposer require google/protobuf创建 .proto 文件
定义一个简单的用户服务。创建文件 user.proto:
syntax = "proto3";
package user;
service UserService { rpc GetUser (UserRequest) returns (UserResponse); rpc ListUsers (Empty) returns (stream UserResponse);}
message UserRequest { int32 id = 1;}
message UserResponse { int32 id = 1; string name = 2; string email = 3;}
message Empty {}从 .proto 生成 PHP 代码
执行命令将 .proto 编译为 PHP 类:
protoc --php_out=./generated --grpc_out=./generated \ --plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin \ user.proto在 generated 文件夹中会出现以下文件:
GPBMetadata/User.php— proto 文件的元数据User/UserRequest.php— 请求类User/UserResponse.php— 响应类User/UserServiceClient.php— 用于调用服务的客户端
在 PHP 中实现 gRPC 服务器
对于服务器端,我们使用官方 grpc 扩展。创建文件 server.php:
<?phprequire_once __DIR__ . '/vendor/autoload.php';require_once __DIR__ . '/generated/User/UserServiceInterface.php';require_once __DIR__ . '/generated/User/UserServiceServer.php';
use Grpc\\Server;use User\\UserRequest;use User\\UserResponse;use User\\UserServiceServer;
class MyUserService extends UserServiceServer{ public function GetUser(\\User\\UserRequest $request): \\User\\UserResponse { $response = new UserResponse(); $response->setId($request->getId()); $response->setName('John Doe'); $response->setEmail('john@exa