gRPC是一个有google推出的、高性能、开源、通用的远程过程调用(RPC)框架。
基本开发流程:
- 在一个 .proto 文件内定义服务
- 用 protocol buffer 编译器生成服务器和客户端代码
- 使用 gRPC 的 Go API 为你的服务实现一个简单的客户端和服务器
定义服务
使用 protocol buffers 去定义 gRPC service 和方法 request 以及 response 的类型。
syntax = "proto3";
package device;
service Device {
rpc PostProperty(PropertyReq) returns (CommonRsp) {}
}
message PropertyReq{
string Attr = 1;
string Value = 2;
}
message CommonRsp{
int32 Code = 1;
string ErrMsg = 2;
}
生成客户端和服务器端代码
通过 protocol buffer 的编译器 protoc来生成
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
go get -u google.golang.org/grpc
protoc --go_out=plugins=grpc:. *.proto
运行命令后在当前目录中生成下面的文件:
- device.pb.go
创建服务器
服务工作有两个部分:
- 实现我们服务定义的生成的服务接口:做我们的服务的实际的“工作”。
- 运行一个 gRPC 服务器,监听来自客户端的请求并返回服务的响应。
启动服务
package device
import (
"context"
"google.golang.org/grpc"
)
type Server struct {
UnimplementedDeviceServer
}
func (this *Server) PostProperty(ctx context.Context, req *PropertyReq) (*CommonRsp, error) {
if req.Attr == "" {
return &CommonRsp{Code: 500, ErrMsg: "Invalid Attr"}, nil
}
// do something
return &CommonRsp{Code: 200, ErrMsg: "OK"}, nil;
}
func RegeisterService(server *grpc.Server) {
RegisterDeviceServer(server, &Server{})
}
服务实现
package device
import (
"context"
"google.golang.org/grpc"
)
type Server struct {
UnimplementedDeviceServer
}
func (this *Server) PostProperty(ctx context.Context, req *PropertyReq) (*CommonRsp, error) {
if req.Attr == "" {
return &CommonRsp{Code: 500, ErrMsg: "Invalid Attr"}, nil
}
// do something
return &CommonRsp{Code: 200, ErrMsg: "OK"}, nil;
}
func RegeisterService(server *grpc.Server) {
RegisterDeviceServer(server, &Server{})
}
创建客户端
package main
import (
"context"
"log"
"time"
"www.github.com/oulp/go/device"
"google.golang.org/grpc"
)
const (
address = "localhost:50051"
)
func main() {
// 建立连接
conn, err := grpc.Dial(address, 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()
// 调用服务
client := device.NewDeviceClient(conn)
rsp, err := client.PostProperty(ctx, &device.PropertyReq{Attr: "A01", Value: "100"})
if err != nil {
log.Fatalf("could not: %v", err)
}
log.Printf("Rsp: %s %s", rsp.GetCode(), rsp.GetErrMsg())
}