grpc和protobuf


grpc

gRPC 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。目前提供 C、Java 和 Go 语言版本,分别是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持. grpc/grpc The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#) - grpc/grpc

Protocol Buffer

其实 是 Google出品的一种轻量 & 高效的结构化数据存储格式,性能比 Json、XML 真的强!太!多! protobuf经历了protobuf2和protobuf3,pb3比pb2简化了很多,目前主流的版本是pb3

优点上

  • 体积更小,序列化和传输的速度更快
  • 使用相对简单维护成本低兼容性好
  • 跨平台,跨语言

缺点上

  • 二进制存储,自释性差
  • XML和Json当道,通用性较差

基于以上特点,我们可以看到在传输数据量较大的需求场景下,Protobuf比XML、Json 更小、更快、使用和维护更简单!

syntax = "proto3";

service Greeter{
  rpc SayHello(HelloRequest) returns (HelloReply){}
}

message HelloRequest{
  string name = 1;
}

message HelloReply{
  string message = 1;
}

Python使用grpc

# 安装grpc与grpc-tools
pip install grpcio  -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install grpcio-tools  -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
# 生成python的protobuf文件
python3 -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I. hello.proto
# server
import grpc
from concurrent import futures
from proto.hello_pb2 import HelloReply
from proto.hello_pb2_grpc import GreeterServicer,add_GreeterServicer_to_server

class Greeter(GreeterServicer):
    def SayHello(self, request, context):
        return HelloReply(message=f"你好,{request.name}")


if __name__ == "__main__":
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    add_GreeterServicer_to_server(Greeter(), server)
    server.add_insecure_port("0.0.0.0:12345")
    server.start()
    server.wait_for_termination()

# client
import grpc
from proto import hello_pb2, hello_pb2_grpc

if __name__ == "__main__":
    with grpc.insecure_channel("localhost:12345") as chan:
        stub = hello_pb2_grpc.GreeterStub(chan)
        rsp = stub.SayHello(hello_pb2.HelloRequest(name="zj"))
        print(rsp.message)

Go语言使用grpc

安装用于生成gRPC服务代码的协议编译器
下载地址:https://github.com/google/protobuf/releases
go install google.golang.org/grpc@latest
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
syntax = "proto3";
option go_package = ".;proto";
service Greeter{
  rpc SayHello(HelloRequest) returns (HelloReply){}
}

message HelloRequest{
  string name = 1;
}

message HelloReply{
  string message = 1;
}

// protoc -I . hello.proto --go_out=plugins=grpc:.
// protoc -I . hello.proto --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:.
// server
package main

import (
    "context"
    "google.golang.org/grpc"
    "net"
    "test/day06/proto"
)

type Server struct {
}

func (s *Server) SayHello(ctx context.Context, req *proto.HelloRequest) (*proto.HelloReply, error) {
    return &proto.HelloReply{Message: "hello" + req.Name}, nil
}

func main() {
    g := grpc.NewServer()
    proto.RegisterGreeterServer(g, &Server{})
    lis, err := net.Listen("tcp", "0.0.0.0:12345")
    if err != nil {
        panic("failed to listen:" + err.Error())
    }
    err = g.Serve(lis)
    if err != nil {
        panic("failed to listen:" + err.Error())
    }
}

// client
package main

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    "test/day06/proto"
)

func main() {
    conn, err := grpc.Dial(":12345", grpc.WithTransportCredentials(insecure.NewCredentials()))
    if err != nil {
        panic("failed to listen:" + err.Error())
    }
    defer conn.Close()
    c := proto.NewGreeterClient(conn)
    r, err := c.SayHello(context.Background(), &proto.HelloRequest{Name: " zj1007"})
    if err != nil {
        panic("failed to listen:" + err.Error())
    }
    fmt.Println(r.Message)
}