concept
- gRPC: A high-performance modern RPC framework
- Protobuf: Cross-platform data exchange protocol (service description is defined in the
.proto
file)
proto file example
The proto/user/user.proto file name is used as the prefix of the pb.go file name of the protoc compilation output
syntax = "proto3";
package user; //用于proto import的包名,一般和.proto文件名一致
option php_package = "./proto/user"; //相对编译指令路径的php输出目录(默认作为php名字空间),必须./开头
option go_package = "./proto/user"; //相对编译指令路径的go输出目录(默认作为go包名),必须./开头
service UserService {
rpc GetUser(UidRequest) returns(UserResponse);
}
message UidRequest {
int64 id = 1;
}
message UserResponse {
int64 id = 1;
string name = 2;
}
PHP platform application
Environmental preparation
sudo yum -y install unzip libtool
git clone --recurse-submodules -b RELEASE_TAG版本号 https://github.com/grpc/grpc
cd grpc && make & sudo make install
# 编译输出文件中:
# grpc/bins/opt/protobuf/protoc:proto文件编译器
# grpc/bins/opt/grpc_php_plugin:PHP插件(配合protoc生成php客户端类)
sudo pecl install grpc
composer require grpc/grpc --profile --prefer-dist --optimize-autoloader
sudo pecl install protobuf
composer require google/protobuf --profile --prefer-dist --optimize-autoloader
PHP plugin to compile pb file
# 项目根目录下
protoc --plugin=protoc-gen-grpc=bins/opt/grpc_php_plugin \
--php_out=.指定输出目录 --grpc_out=.指定输出目录 proto/user/user.proto
Service call example
The php platform only supports gRPC client, not gRPC server
//客户端
$request = (new UidRequest())->setId($id);
$client = new UserServiceClient("gRPC主机:端口", [
'credentials' => ChannelCredentials::createInsecure(),
'timeout' => 1000000,
]);
list($reponse, $status) = $client->GetUser($request)->wait();
$reponse->getId();
$reponse->getName();
$client->close();
Golang platform application
Environmental preparation
https://github.com/protocolbuffers/protobuf/releases #下载对应系统的protoc编译器,"mv bin/protoc $GOPATH/bin"
go get google.golang.org/protobuf/cmd/protoc-gen-go
go get google.golang.org/grpc/cmd/protoc-gen-go-grpc
go get google.golang.org/grpc
Go plugin to compile pb file
# 项目根目录下
protoc --go_out=.指定输出目录 --go-grpc_out=.指定输出目录 proto/user/user.proto
# 产出文件
# * user.pb.go:请求响应消息体定义
# * user_grpc.pb.go:客户端服务端接口定义,客户端已有完整实现,服务端有一个用于类型内嵌的空实现
Service call example
import protouser "模块名/proto/user"
//服务端
type server struct{
protouser.UnimplementedUserServiceServer
}
func (s *server) GetUser(ctx context.Context, in *protouser.UidRequest) (*protouser.UserResponse, error) {
return &protouser.UserResponse{Id: "", Name: ""},nil
}
func main() {
lis, err := net.Listen("tcp", "localhost:9090")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
protouser.RegisterUserServiceServer(s, &server{})
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
//客户端
func main() {
conn, err := grpc.Dial("localhost:9090", grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := protouser.NewUserServiceClient(conn).GetUser(ctx, &protouser.UidRequest{Id: "100"})
if err != nil {
log.Fatalf("failed to call: %v", err)
}
fmt.Println(r.name)
}
{{o.name}}
{{m.name}}