grpc使用一览子

  • 2019 年 11 月 21 日
  • 笔记

grpc使用起来很HAPPY。以最近做的一个评论微服务举个栗子。

创建proto文件。

主要就是request, response两大类 base_req.proto

syntax = "proto3";  package customer;      // The  service definition.  service CommentReq {    // Create a new BaseReq - A simple RPC    rpc CreateComment (CommentRequest) returns (CommonResponse) {}    rpc DeleteComment (CommentRequest) returns (CommonResponse) {}    rpc ListComment (ListCommentRequest) returns (ListCommentResponse) {}    rpc CommentCount (CommentCountRequest) returns (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;    int64 creator_source = 4;    int64 reply_uid = 5;    int64 reply_source = 6;    int64 target_id = 7;  // 评论来源主体的id,可能是视频,帖子    int64 source = 8; // 评论来源主体的来源,可能是1,2    int64 created_at = 9;    string extra = 10;  // 一个json dump的字符串  }

安装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

如果proto文件无误,目录下将出现base_req.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() {      lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))      if err != nil {          log.Fatalf("failed to listen: %v", err)      }      s := grpc.NewServer()      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客户端

首先把库装好

python -m pip install grpcio --ignore-installed  python -m pip install grpcio-tools googleapis-common-protos    pip install protobuf==3.6.0  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)

差不多就酱了。