gRPC 用于 PHP:库和示例
gRPC 是一种由 Google 开发的现代高性能远程过程调用(RPC)框架。它使用 HTTP/2 进行传输,使用 Protocol Buffers(protobuf)进行数据序列化,并支持包括 PHP 在内的多种语言。在本文中,我们将介绍如何将 gRPC 集成到 PHP 项目中,需要哪些库,并编写一个客户端-服务器交互的工作示例。
为什么在 PHP 中需要 gRPC?
传统的 REST API 通常通过 JSON 和 HTTP/1.1 工作,这会导致数据冗余和序列化缓慢。gRPC 解决了这些问题:
- 二进制协议 — protobuf 比 JSON 占用更少的空间,处理速度更快。
- HTTP/2 — 多路复用、头部压缩、流式传输。
- 强类型 — 契约在 .proto 文件中描述,简化了开发和调试。
- 双向流式传输 — 服务器和客户端可以异步交换数据。
PHP 中 gRPC 的主要库
在 PHP 中使用 gRPC 需要两个组件:
- grpc.so — PHP 扩展(C 扩展),实现 HTTP/2 和 gRPC 协议。
- protobuf.so — 用于 protobuf 序列化的扩展(替代方案是纯 PHP 包
google/protobuf)。 - Composer 包:
grpc/grpc和google/protobuf。
推荐的安装方式是通过 PECL(扩展)和 Composer(依赖)。
安装 gRPC 和 protobuf
对于 Linux 服务器(Ubuntu/Debian):
# 通过 PECL 安装扩展sudo pecl install grpcsudo pecl install protobuf
# 添加到 php.iniecho "extension=grpc.so" >> /etc/php/8.2/cli/php.iniecho "extension=protobuf.so" >> /etc/php/8.2/cli/php.ini对于 Windows,请从 PECL 下载 DLL 文件,并在 php.ini 中指定它们。
然后通过 Composer 安装库:
composer require grpc/grpccomposer require google/protobuf创建 .proto 文件
让我们描述一个用于用户管理的服务。创建文件 user.proto:
syntax = "proto3";
package user;
service UserService { rpc GetUser (UserRequest) returns (UserResponse); rpc ListUsers (Empty) returns (UserList);}
message UserRequest { int32 id = 1;}
message UserResponse { int32 id = 1; string name = 2; string email = 3;}
message Empty {}
message UserList { repeated UserResponse users = 1;}从 .proto 生成 PHP 类
安装 protoc 和 PHP 插件:
# 从 https://github.com/protocolbuffers/protobuf/releases 下载 protoc# 然后生成代码:protoc --php_out=./generated --grpc_out=./generated --plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin user.proto在 generated 文件夹中将出现类:UserRequest、UserResponse、UserServiceClient 等。
PHP gRPC 服务器示例
让我们创建一个响应请求的服务器。文件 server.php:
require_once __DIR__ . '/vendor/autoload.php';require_once __DIR__ . '/generated/UserServiceServer.php';
use Grpc\\Server;use User\\UserServiceServer;use User\\UserRequest;use User\\UserResponse;
class MyUserService extends UserServiceServer{ public function GetUser(\\Grpc\\ServerCallReader $request, \\Grpc\\ServerCallWriter $response, \\Grpc\\ServerContext $context): void { $req = $request->read(); $id = $req->getId();
$user = new UserResponse(); $user->setId($id); $