grpc使用一览子 grpc使用起来很HAPPY。以最近做的一个评论微服务举个栗子。 ## 创建proto文件。 主要就是request, response两大类 base_req.proto ``` syntax = "proto3"; package customer; option go_package = "git.xxx.com/comment_svc/base_req"; // The service definition. service CommentReq { rpc CreateComment (CommentRequest) returns (CommonResponse) {} rpc ReadComment(stream CommentRequest) returns (stream CommonResponse) {} //双向流 } // Request message for creating a new customer message CommentRequest { int64 app = 1; Comment comment = 2; } message CommonResponse { int64 err = 1; string err_msg = 2; string extra = 3; } message CommentCountRequest { int64 app = 1; int64 target_id = 2; int64 source = 3; } message ListCommentRequest { int64 app = 1; int64 target_id = 2; int64 source = 3; int64 last_id = 4; int64 count = 5; string order = 6; } message ListCommentResponse { int64 err = 1; string err_msg = 2; int64 last_id = 3; repeated Comment comment = 4; } message Comment { int64 comment_id = 1; string content = 2; int64 creator_id = 3; } ``` ## 安装protobuf 然后,要用protobuf把它编译成对应的语言代码。 首先安装protoc,偷个懒,别人早就编译好了。直接用就行。 ``` go get -u github.com/golang/protobuf/protoc-gen-go wget https://github.com/protocolbuffers/protobuf/releases/download/v3.6.1/protoc-3.6.1-linux-x86_64.zip mkdir protoc cd protoc mv ../protoc-3.6.1-linux-x86_64.zip . unzip protoc-3.6.1-linux-x86_64.zip export PATH=$PATH:/home/protoc/bin ``` 定位到.proto的目录下,使用这个命令生成go的对应文件 ``` protoc --go_out=plugins=grpc:. base_req.proto // 新版protoc改了plugins的方式 protoc --go-grpc_out=. --go_out=. base_req.proto // 此时,生成的grpc服务会出现 pb.mustEmbedUnimplementedXXXServer,在结构体中包含pb.UnimplementedXXServer即可 ``` 如果proto文件无误,目录下将出现`base_req.pb.go/base_req_grpc.pb.go`文件。 ## go使用grpc 首先go get下面的东东 ``` go get google.golang.org/grpc/reflection go get github.com/golang/protobuf/proto go get google.golang.org/grpc ``` 直接来代码了: 服务端启动: ``` package main import ( pb "base_req" "server" "google.golang.org/grpc" "google.golang.org/grpc/reflection" ) func main() { // 服务端配置keepalive,在使用stream的时候特别重要。 var keepAliveArgs = keepalive.ServerParameters{ Time: 1 * time.Minute, Timeout: 15 * time.Second, MaxConnectionIdle: 5 * time.Minute, } lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) if err != nil { log.Fatalf("failed to listen: %v", err) } s := grpc.NewServer( grpc.KeepaliveParams(keepAliveArgs), grpc.MaxSendMsgSize(1024*1024*4), // 最大消息4M // grpc.ReadBufferSize(1024), // grpc.WriteBufferSize(1024), // grpc.MaxConcurrentStreams(10), ) pb.RegisterCommentReqServer(s, &server.Server{}) pb.RegisterLikeReqServer(s, &server.Server{}) // Register reflection service on gRPC server. reflection.Register(s) if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } } ``` server文件,注意,proto定义的函数都要实现。 ``` package server import ( pb "base_req" "golang.org/x/net/context" ) type Server struct{} // SayHello implements helloworld.GreeterServer func (s *Server) CreateComment(ctx context.Context, in *pb.CommentRequest) (*pb.CommonResponse, error) { ... return &pb.CommonResponse{Err: 0, ErrMsg: in.Comment.Content}, nil } .... 省略10000字 ``` 客户端: ``` conn, err := grpc.Dial(address, grpc.WithInsecure()) if err != nil { log.Fatalf("did not connect: %v", err) } defer conn.Close() c := pb.NewCommentReqClient(conn) db := sqlutils.GetCommentDB() ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) defer cancel() // 执行函数了!! resp, err := c.CreateComment(ctx, &pb.CommentRequest{App: 2, Comment: &pb.Comment{ Content: "hello", CreatorId: 123, CreatorSource: 456, ReplyUid: 0, ReplySource: 456, TargetId: 1, Source: 2, Extra: "", }}) ``` ## python客户端 首先把库装好 ``` python3 -m pip install grpcio --ignore-installed python3 -m pip install grpcio-tools googleapis-common-protos python3 -m pip install protobuf python3 -m pip install git+https://github.com/kaporzhu/protobuf-to-dict.git ``` 生成py版的proto代码文件 ``` python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. base_req.proto ``` 此时,应该出现了base_req_pb2.py和base_req_pb2_grpc.py文件,把它cp到项目中去。引用它。 单向流: ``` import grpc import base_req_pb2 import base_req_pb2_grpc channel = grpc.insecure_channel(COMMUNITY_RPC_URL) comment_stub = base_req_pb2_grpc.CommentReqStub(channel) response = comment_stub.CreateComment(base_req_pb2. CommentRequest( app=2, comment=base_req_pb2. Comment( content=self.content, creator_id=int(self.creator_id), creator_source=int(self.creator_source), reply_uid=int(self.reply_uid), reply_source=int(self.reply_source), target_id=int(self.target_id), source=int(self.source), extra=self.extra, ))) ``` 双向流: ``` channel = grpc.insecure_channel("119.29.46.85:30112") read_stub = msg_proxy_pb2_grpc.MsgReadProxyStub(channel) secret_id = "2166479cc7c24166afcfa545e5" secret_key = "097751e9bb2741b2ad9eabe327" timestamp = str(int(time.time())) msg = msg_proxy_pb2.Msg( SecretId=secret_id, Signature=gen_sign(secret_id, secret_key, timestamp), Timestamp=timestamp, Topic="float_object_detect", GroupId="testpig", JobID="123", ) def ge_req(): yield msg req = ge_req() response = read_stub.ReadSubscribeTopic(req) for rec in response: print(rec.Buffer) ``` 差不多就酱了。 ## 获取一个proto对象,将它转换为[]byte ``` import "github.com/golang/protobuf/proto" ... attrByte, err := proto.Marshal(attrData) ``` ## pb json动态转换 https://www.superpig.win/blog/details/skwvigfr ## 从grpc中获取extension的值 https://www.superpig.win/blog/details/tohsefta 来自 大脸猫 写于 2018-11-01 11:40 -- 更新于2023-07-28 15:35 -- 0 条评论