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)
差不多就醬了。