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)

差不多就醬了。

Exit mobile version