版本
go version
go1.19.1 darwin/arm64
protoc --version
libprotoc 3.21.9
projectpath 代表项目根目录
Go服务端
初始化golang项目,编写proto文件
// projectpath/proto/link.proto
syntax = "proto3";
package proto;
option go_package = "/proto";
service Link{
rpc GetLink(GetLinkRequest) returns (GetLinkResponse){}
}
message GetLinkRequest{
int32 driver = 1;
string linkId = 2;
string token = 3;
}
message GetLinkResponse {
int32 code = 1;
string link = 2;
string pwd = 3;
}
安装所需工具
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28 //用于生成xx.pb.go文件 主要是link.proto里面的message对应的go代码
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2 //用于生成xx_grpc.pb.go 即grpc服务的go版本服务端和客户端
//安装之后查看是否安装成功
protoc-gen-go --version
protoc-gen-go v1.28.1
protoc-gen-go-grpc --version
protoc-gen-go-grpc 1.2.0
如果提示未找到命令的话
export PATH="$PATH:$(go env GOPATH)/bin" //可以加到~/.zshrc 或者 ~/.bashrc文件中
生成grpc服务go相关代码
//在projectpath/proto目录下执行
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative link.proto
//在projectpath/proto下新增了link.pb.go和link_grpc.pb.go文件
编写服务端的的代码
package main
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"grpc.demo.com/proto"
"log"
"net"
)
func main() {
lis, err := net.Listen("tcp", "127.0.0.1:50001")
if err != nil {
log.Fatalln("listen failed")
}
s := grpc.NewServer()
proto.RegisterLinkServer(s, &Server{})
reflection.Register(s)
err = s.Serve(lis)
if err != nil {
log.Fatalln("serve failed")
}
}
type Server struct {
proto.UnimplementedLinkServer
}
func (s *Server) GetLink(ctx context.Context, req *proto.GetLinkRequest) (*proto.GetLinkResponse, error) {
return &proto.GetLinkResponse{
Code: 0,
Link: "test",
Pwd: "none",
}, nil
}
PHP客户端
工具
要下载很多东西,准备好网络工具
项目外建一个文件夹,cd进去执行
git clone -b v1.45.x --depth=1 https://github.com/grpc/grpc --shallow-submodules --recurse-submodules
cd grpc
mkdir -p cmake/build
cd cmake/build
cmake ../..
make protoc grpc_php_plugin
# cmake 和 make时可能会出现warning,没有error就没问题
echo $(pwd)/grpc_php_plugin //这里就是编译后的grpc-php插件位置
生成php客户端的代码
回到go项目的proto目录下
protoc --php_out=. --grpc_out=. --plugin=protoc-gen-grpc=/Users/bao/Documents/Github/grpc/cmake/build/grpc_php_plugin link.proto
//最终的目录
├── go.mod
├── go.sum
├── proto
│ ├── GPBMetadata
│ │ └── Link.php
│ ├── Proto
│ │ ├── GetLinkRequest.php
│ │ ├── GetLinkResponse.php
│ │ └── LinkClient.php
│ ├── link.pb.go
│ ├── link.proto
│ └── link_grpc.pb.go
└── server.go
//在proto下会新增GPBMetadata文件夹,生成了Link.php,在proto的Proto文件夹下生成了GetLinkRequest.php,GetLinkResponse.php,LinkClient.php文件,复制到laravel项目的根目录下proto文件夹中
composer 安装 grpc/grpc ^v1.3.0,google/protobuf ^v3.3.0
php调用
项目用的laradock,确保安装了grpc.so,protobuf.so并开启了 ,composer psr-4 自动加载
{
"autoload": {
"psr-4": {
"Proto\\": "proto/",
"GPBMetadata\\": "proto/",
}
},
$client = new LinkClient('host.docker.internal', [
'credentials' => ChannelCredentials::createInsecure()
]);
$grpcRequest = new GetLinkRequest();
$grpcRequest->setLinkId("test");
$grpcRequest->setDriver(12);
$grpcRequest->setToken("testtoken");
$resp = $client->GetLink($grpcRequest)->wait();
dd($resp);
wait返回值为数组,第一个元素可以转换成proto生成的response,这里是GetLinkResponse,第二个是meta信息关联数组,里面code为0时请求成功,其他值为grpc调用失败,需要处理
array:2 [▼ // app/Http/Controllers/IndexController.php:38
0 => Proto\GetLinkResponse {#2004 ▼
#code: 2
#link: ""
#pwd: "ocod"
-desc: Google\Protobuf\Internal\Descriptor {#2042 ▼
-full_name: "proto.GetLinkResponse"
-field: array:3 [▶]
-json_to_field: array:3 [▶]
-name_to_field: array:3 [▶]
-index_to_field: array:3 [▶]
-nested_type: []
-enum_type: []
-klass: "Proto\GetLinkResponse"
-legacy_klass: "Proto\GetLinkResponse"
-previous_klass: "Proto\GetLinkResponse"
-options: null
-oneof_decl: []
-public_desc: Google\Protobuf\Descriptor {#2043 ▼
-internal_desc: Google\Protobuf\Internal\Descriptor {#2042}
}
}
-unknown: ""
}
1 => {#2034 ▼
+"metadata": []
+"code": 0
+"details": ""
}
]
如果有端口连通性问题可以用telnet,或者
# Download image
docker pull fullstorydev/grpcurl:latest
# Run the tool
docker run fullstorydev/grpcurl api.grpc.me:443 list