本文目录导读:

在 PHP 中使用 gRPC-Web 主要有两种方式,我来详细说明:
使用 gRPC-Web 代理方案
这是最常用的方式,通过代理将 gRPC-Web 请求转换为标准 gRPC 请求。
1 搭建 gRPC 服务端
创建标准的 gRPC 服务:
// proto/helloworld.proto
syntax = "proto3";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
生成 PHP 代码:
protoc --php_out=generated --grpc_out=generated --plugin=protoc-gen-grpc=/path/to/grpc_php_plugin helloworld.proto
创建 gRPC 服务端:
// server.php
require 'vendor/autoload.php';
use Grpc\Server;
use Helloworld\GreeterInterface;
use Helloworld\HelloReply;
class GreeterService implements GreeterInterface {
public function SayHello(\Helloworld\HelloRequest $request, \Grpc\ServerContext $context): \Helloworld\HelloReply {
$reply = new HelloReply();
$reply->setMessage("Hello " . $request->getName());
return $reply;
}
}
$server = new Server();
$server->addHttp2Port('0.0.0.0:50051');
$server->register(GreeterService::class, new GreeterService());
$server->run();
2 配置代理
使用 Envoy 或 grpc-web 代理:
Envoy 配置示例:
# envoy.yaml
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match: { prefix: "/" }
route:
cluster: greeter_service
timeout: 0s
max_stream_duration:
grpc_timeout_header_max: 0s
cors:
allow_origin_string_match:
- prefix: "*"
allow_methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
allow_headers: keep-alive, user-agent, cache-control, content-type, content-transfer-encoding, custom-header-1, x-accept-content-transfer-encoding, x-accept-response-streaming, x-user-agent, x-grpc-web
expose_headers: grpc-status, grpc-message
http_filters:
- name: envoy.filters.http.grpc_web
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
http_protocol_options:
accept_http10: true
clusters:
- name: greeter_service
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options: {}
load_assignment:
cluster_name: greeter_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 127.0.0.1, port_value: 50051 }
PHP 客户端实现
1 使用 grpc-web-client 库
composer require grpc/grpc-php composer require grpc-web/grpc-web-client
// client.php
require 'vendor/autoload.php';
use Helloworld\HelloRequest;
use Helloworld\GreeterClient;
use Grpc\ChannelCredentials;
use GrpcWeb\Client as GrpcWebClient;
// 创建 gRPC 客户端
$client = new GreeterClient('localhost:8080', [
'credentials' => ChannelCredentials::createInsecure(),
]);
// 创建请求
$request = new HelloRequest();
$request->setName('World');
// 调用服务
$response = $client->SayHello($request);
// 处理响应
if ($response->getCode() === \Grpc\STATUS_OK) {
echo $response->getMessage() . "\n";
} else {
echo "Error: " . $response->getMessage() . "\n";
}
2 使用 cURL 或 HTTP 客户端
如果你需要更直接的控制,可以使用 cURL:
function callGrpcWeb($method, $body) {
$url = 'http://localhost:8080/' . $method;
$ch = curl_init($url);
// 设置请求头
$headers = [
'Content-Type: application/grpc-web+proto',
'X-Grpc-Web-Encoding: base64',
'X-Grpc-Time-Out: 10000',
];
// 创建 protobuf 消息
$request = new HelloRequest();
$request->setName('World');
$binaryBody = $request->serializeToString();
// 编码为 base64
$encodedBody = base64_encode($binaryBody);
curl_setopt($ch, CURLOPT_POSTFIELDS, $encodedBody);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 执行请求
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
// 解码响应
$decodedResponse = base64_decode($response);
// 解析响应消息
$reply = new HelloReply();
$reply->mergeFromString($decodedResponse);
return $reply->getMessage();
}
return null;
}
// 调用示例
echo callGrpcWeb('/helloworld.Greeter/SayHello', '');
完整的现代 PHP 项目示例
使用 PHP 8+ 和现代框架的完整示例:
// src/GrpcClient.php
namespace App\Services;
use Grpc\ChannelCredentials;
use Helloworld\GreeterClient;
use Helloworld\HelloRequest;
class GrpcClientService {
private $client;
public function __construct($endpoint = 'localhost:8080') {
$this->client = new GreeterClient($endpoint, [
'credentials' => ChannelCredentials::createInsecure(),
]);
}
public function sayHello($name) {
$request = new HelloRequest();
$request->setName($name);
list($response, $status) = $this->client->SayHello($request)->wait();
if ($status->code !== \Grpc\STATUS_OK) {
throw new \Exception('gRPC call failed: ' . $status->details);
}
return $response->getMessage();
}
}
// 使用示例
try {
$grpcService = new GrpcClientService();
$message = $grpcService->sayHello('PHP User');
echo $message; // 输出: Hello PHP User
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
配置和注意事项
前端集成示例:
// 前端 JavaScript 使用
const client = new GreeterClient('http://localhost:8080');
const request = new HelloRequest();
request.setName('Web User');
client.sayHello(request, {}, (err, response) => {
if (response) {
console.log('Response:', response.getMessage());
}
});
常见问题处理:
- CORS 配置:确保代理配置了正确的 CORS 头
- 超时设置:处理长连接的 gRPC 流式调用
- 错误处理:统一处理 gRPC 状态码
- 性能优化:考虑连接池和重试机制
生产环境建议:
// 生产环境配置
$config = [
'endpoint' => 'grpc-backend:50051',
'credentials' => [
'call_injector' => [
'grpc.trace_flag',
'grpc.service_name_dns' => 'my-service',
],
],
'retry' => [
'max_retries' => 3,
'backoff' => 1000,
],
];
$client = new GreeterClient($config['endpoint'], $config);
这就是在 PHP 中使用 gRPC-Web 的完整方案,主要优势是客户端不需要安装特殊的 gRPC 扩展,只需要 HTTP/1.1 和 base64 编码即可,非常适合浏览器环境。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播