*由于篇幅限制,本文只能提供一个简单的使用流程,不会对具体的概念深入解释
你至少需要了解的基本知识: PHP, Composer, Go, ProtoBuf, gRPC
#第一步:编写 .proto 文件
在本例中,我们定义一个计算器类,拥有相加,相减两个方法,以及定义参数和返回值的类型
syntax = "proto3"; //使用的proto3语法版本
package grpc_test; //包名//定义一个服务,包含两个方法
service Calculator {
rpc Add (RequestData) returns (ResponseData) {}
rpc Reduce (RequestData) returns (ResponseData) {}
}//定义一个请求类型
message RequestData {
int32 a= 1;
int32 b= 2;
}//定义一个返回类型
message ResponseData {
int32 c= 1;
}
#使用protoc编译器编译 .proto 文件
protoc -I ./proto \
./proto/grpc_test.proto \--php_out=./php_src \--go_out=plugins=grpc:./go_src \--grpc_out=./php_src \--plugin=protoc-gen-grpc=/opt/share/grpc_php_plug
说明:
1 指定.proto文件目录
2 指定.proto文件位置
3 根据proto文件定义生成对应php代码
4 根据proto文件定义生成对应的go代码
5 输出grpc的php调用客户端代码
6 grpc_php_plugin插件位置(这个需要下载源代码编译得出)
该命令执行后,会在go_src下生成相关的go代码,php_src下生成对应的php代码
#利用生成的go代码编写gRPC服务
package main
import ("context"
"fmt"
"google.golang.org/grpc"pb"grpc_test/go_src" //引入了生成的go代码
"log"
"net")
func main() {
lis, err := net.Listen("tcp", "192.168.0.220:8888")if err !=nil {
log.Fatalf("failed to listen: %v", err)
}
s :=grpc.NewServer()
pb.RegisterCalculatorServer(s,&server{})if err := s.Serve(lis); err !=nil {
log.Fatalf("failed to serve: %v", err)
}
}
type server struct {
pb.UnimplementedCalculatorServer
}
func (s*server) Add(ctx context.Context, in *pb.RequestData) (*pb.ResponseData, error) {fmt.Println("add:")
return&pb.ResponseData{
C:in.A + in.B,
}, nil
}
func (s*server) Reduce(ctx context.Context, in *pb.RequestData) (*pb.ResponseData, error) {fmt.Println("reduce:")
return&pb.ResponseData{
C:in.A - in.B,
}, nil
}
#编译并运行代码,服务就开始监听了
#准备PHP环境
这一部分稍微就麻烦点,需要安装两个扩展grpc,protobuf 可以通过pecl安装:
pecl installgrpc
peclinstallprotobuf
安装后在对应的php.ini文件中添加
extension=grpc.so
extension=protobuf.so
将ptotoc编译生成的php代码添加到composer.json中
"psr-4": {
"GPBMetadata\\":"app/grpc/GPBMetadata/",
"Grpc_test\\":"app/grpc/Grpc_test/"
},
#编写PHP客户端调用代码
namespace App\grpc;
use Grpc\ChannelCredentials;
use Grpc_test\CalculatorClient;
use Grpc_test\RequestData;
class Grpctest
{
publicfunctionadd() {
$ins= new CalculatorClient("192.168.0.220:8888",['credentials' =>ChannelCredentials::createInsecure()
]);
$req=new RequestData();
$req->setA(40);
$req->setB(20);
list($res, $status)= $ins->Reduce($req)->wait();dd($res->getC());
}
}
如果一切顺利,这里应该打印出最终结果 20
#最后梳理一下整个流程
1.首先编写proto文件
2.生成对应的服务端和客户端辅助代码
3.借助辅助代码编写服务端和客户端