gRPC与Protobuf实践

目录

官方网站

windows环境安装protoc

下载安装包

下载文件 protoc-3.12.3-win64.zip,解压后 protoc.exe 拷贝到 c:\windows\system32

执行protoc –version命令检查是否安装成功


实践-目录结构


实践-proto文件

其中首先编写 protobuf/customer/customer.proto 文件

syntax = "proto3";
package customer;

// The Customer service definition.
service Customer {
  // Get all Customers with filter - A server-to-client streaming RPC.
  rpc GetCustomers(CustomerFilter) returns (stream CustomerRequest) {}
  // Create a new Customer - A simple RPC
  rpc CreateCustomer (CustomerRequest) returns (CustomerResponse) {}
}

// Request message for creating a new customer
message CustomerRequest {
  int32 id = 1;  // Unique ID number for a Customer.
  string name = 2;
  string email = 3;
  string phone= 4;

  message Address {
    string street = 1;
    string city = 2;
    string state = 3;
    string zip = 4;
    bool isShippingAddress = 5;
  }

  repeated Address addresses = 5;
}

message CustomerResponse {
  int32 id = 1;
  bool success = 2;
}
message CustomerFilter {
  string keyword = 1;
}

运行命令生成 customer.pb.go 文件

cd ./protobuf/customer

protoc --go_out=plugins=grpc:. customer.proto

运行以上命令可能会出现报错

>protoc --go_out=plugins=grpc:. customer.proto
'protoc-gen-go' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

解决方式:

go install github.com/golang/protobuf/protoc-gen-go

其中可能会出现包缺失,缺失的包如果go get不下来,就去github上下载后,按照包路径放到指定位置

go.dev 包搜索

问题处理完成后,再次执行命令, 运行结果如下, 成功生成文件 customer.pb.go

annaLocalTest\protobuf\customer>protoc --go_out=plugins=grpc:. customer.proto
2020/07/08 11:36:32 WARNING: Missing 'go_package' option in "customer.proto",
please specify it with the full Go package path as
a future release of protoc-gen-go will require this be specified.
See https://developers.google.com/protocol-buffers/docs/reference/go-generated#package for more information.

实践-server文件
package main

import (
    "log"
    "net"
    "strings"

    "golang.org/x/net/context"
    "google.golang.org/grpc"

    pb "annaLocalTest/protobuf/customer"
)

const (
    port = ":50051"
)

// server is used to implement customer.CustomerServer.
type server struct {
    savedCustomers []*pb.CustomerRequest
}

// CreateCustomer creates a new Customer
func (s *server) CreateCustomer(ctx context.Context, in *pb.CustomerRequest) (*pb.CustomerResponse, error) {
    s.savedCustomers = append(s.savedCustomers, in)
    return &pb.CustomerResponse{Id: in.Id, Success: true}, nil
}

// GetCustomers returns all customers by given filter
func (s *server) GetCustomers(filter *pb.CustomerFilter, stream pb.Customer_GetCustomersServer) error {
    for _, customer := range s.savedCustomers {
        if filter.Keyword != "" {
            if !strings.Contains(customer.Name, filter.Keyword) {
                continue
            }
        }
        if err := stream.Send(customer); err != nil {
            return err
        }
    }
    return nil
}

func main() {
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    // Creates a new gRPC server
    s := grpc.NewServer()
    pb.RegisterCustomerServer(s, &server{})
    s.Serve(lis)
}

实践-client文件
package main

import (
    "io"
    "log"

    "golang.org/x/net/context"
    "google.golang.org/grpc"

    pb "annaLocalTest/protobuf/customer"
)

const (
    address = "localhost:50051"
)

// createCustomer calls the RPC method CreateCustomer of CustomerServer
func createCustomer(client pb.CustomerClient, customer *pb.CustomerRequest) {
    resp, err := client.CreateCustomer(context.Background(), customer)
    if err != nil {
        log.Fatalf("Could not create Customer: %v", err)
    }
    if resp.Success {
        log.Printf("A new Customer has been added with id: %d", resp.Id)
    }
}

// getCustomers calls the RPC method GetCustomers of CustomerServer
func getCustomers(client pb.CustomerClient, filter *pb.CustomerFilter) {
    // calling the streaming API
    stream, err := client.GetCustomers(context.Background(), filter)
    if err != nil {
        log.Fatalf("Error on get customers: %v", err)
    }
    for {
        customer, err := stream.Recv()
        if err == io.EOF {
            break
        }
        if err != nil {
            log.Fatalf("%v.GetCustomers(_) = _, %v", client, err)
        }
        log.Printf("Customer: %v", customer)
    }
}
func main() {
    // Set up a connection to the gRPC server.
    conn, err := grpc.Dial(address, grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    // Creates a new CustomerClient
    client := pb.NewCustomerClient(conn)

    customer := &pb.CustomerRequest{
        Id:    101,
        Name:  "Shiju Varghese",
        Email: "shiju@xyz.com",
        Phone: "732-757-2923",
        Addresses: []*pb.CustomerRequest_Address{
            &pb.CustomerRequest_Address{
                Street:            "1 Mission Street",
                City:              "San Francisco",
                State:             "CA",
                Zip:               "94105",
                IsShippingAddress: false,
            },
            &pb.CustomerRequest_Address{
                Street:            "Greenfield",
                City:              "Kochi",
                State:             "KL",
                Zip:               "68356",
                IsShippingAddress: true,
            },
        },
    }

    // Create a new customer
    createCustomer(client, customer)

    customer = &pb.CustomerRequest{
        Id:    102,
        Name:  "Irene Rose",
        Email: "irene@xyz.com",
        Phone: "732-757-2924",
        Addresses: []*pb.CustomerRequest_Address{
            &pb.CustomerRequest_Address{
                Street:            "1 Mission Street",
                City:              "San Francisco",
                State:             "CA",
                Zip:               "94105",
                IsShippingAddress: true,
            },
        },
    }

    // Create a new customer
    createCustomer(client, customer)
    // Filter with an empty Keyword
    filter := &pb.CustomerFilter{Keyword: ""}
    getCustomers(client, filter)
}

分别运行server与client
2020/07/09 10:10:07 A new Customer has been added with id: 101
2020/07/09 10:10:07 A new Customer has been added with id: 102
2020/07/09 10:10:07 Customer: id:101 name:"Shiju Varghese" email:"shiju@xyz.com" phone:"732-757-2923" addresses:{street:"1 Mission Street" city:"San Francisco" state:"CA" zip:"94105"} addresses:{street:"Greenfield" city:"Kochi" state:"KL" zip:"68356" isShippingAddress:true}
2020/07/09 10:10:07 Customer: id:102 name:"Irene Rose" email:"irene@xyz.com" phone:"732-757-2924" addresses:{street:"1 Mission Street" city:"San Francisco" state:"CA" zip:"94105" isShippingAddress:true}