gRPC Learning Notes

gRPC Learning Notes

1. Introduction to gRPC

gRPC It is a high performance, universal open source RPC framework designed by Google for mobile application development based on HTTP/2 protocol standards, based on ProtoBuf(Protocol Buffers) serialization protocol, and supports many development languages.

[External chain picture transfer failed, source may have anti-theft chain mechanism, it is recommended to save the picture and upload it directly (img-ErO385KK-16406221958) (C:Usersv_rwsnowguoDesktopGallerypic112Snipaste_2021-12-03_16-09-45.png)]

1.1 gRPC vs. Restful API

Both gRPC and restful APIs provide a set of communication mechanisms for server/client model communication, and both use HTTP as the underlying transport protocol (strictly speaking, gRPC uses http2.0, whereas restful API does not). However, gRPC has some unique advantages, as follows:

  • gRPC can define interfaces through protobuf, which allows stricter interface constraints.
  • With protobuf, data can be serialized into binary encoding, which greatly reduces the amount of data that needs to be transmitted, thereby greatly improving performance.
  • gRPC can easily support streaming communication (streaming mode is theoretically available through http2.0, but restful api for web services seems to be rarely used. Usually streaming data applications, such as video streaming, use special protocols such as HLS, RTMP, etc. These are not our usual web services, but have special server applications.)

1.2 Four types of service methods

  • A single RPC, in which the client sends a request to the server and gets a response from the server, is like a normal function call.

    rpc SayHello(HelloRequest) returns (HelloResponse);
    
  • Server-side streaming RPC, where a client sends a request to a server to get a stream of data to read a series of messages. Clients read from the returned stream until no more messages are available.

    rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
    
  • Client-side streaming RPC, in which the client writes and sends a series of messages to the server using one of the data streams provided. Once the client finishes writing messages, it waits for the server to read them and return a reply.

    rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
    
  • Two-way streaming RPC, where both sides can send a series of messages through a read-write data stream. The two data flow operations are independent, so the client and the server can read and write in any order they want.

    rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
    

2. Protobuf

Protobuf is an open source serialization protocol framework developed by google, similar to XML,JSON, which uses protocol serialization for data storage and reading. Compared with XML, it is simpler to define data format, data access interface can be generated automatically, and developer development speed is accelerated

2.1 Installation

win Installation

pip install grpcio-tools

reach https://github.com/protocolbuffers/protobuf/releases Download the corresponding installation package and protoc.exe placed under PATH

ubuntu installation

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

reach https://github.com/protocolbuffers/protobuf/releases Download the corresponding installation package and place the protoc under PATH

2.2 Generating code using protoc

# python
protoc --python_out=. api.proto

# go
protoc --go_out=plugins=grpc:. api.proto

2.2 protobuf syntax

Using Message Definition (class), the field format is as follows

[rules][data_type] [data_name] = [number] [default = obj]

Rules: Rules that define the variable

  • Required: required
  • Optional: optional. If no optional field value is set, default is used
  • Repeated: can be repeated any number of times, including zero times, similar to an array.

DataType: Data type

Common data types are int32, int64, float, double, bool, string, bytes

DataName: Field name

Number: Unique numeric identifier

Protobuf is a key-value format that maps member names to number s so that data can be serialized. Each data field has a unique numeric identifier. These identifiers are used to identify the binary format of the field in the message and the type in use should not be arbitrarily changed. It is important to note that identities within [1-15] take up only one byte of encoding, including identifiers and field types. Identifiers between [16-2047] take up two bytes.

Example

syntax = "proto2";
 
message Person {
  required int32 age = 1;
  required string name = 2;
}
 
message Family {
  repeated Person person = 1;
}

3. grpc Project

[External chain picture transfer failed, source station may have anti-theft chain mechanism, it is recommended to save the picture and upload it directly (img-2lagTcg3-16406221959) (C:\Usersv_rwsnowguo\DesktopGallerypic\112Snipa_2021-12-16_10-26-38.png)]

3.1 go.mod

module go-study

go 1.17

require (
	google.golang.org/grpc v1.42.0
	google.golang.org/protobuf v1.27.1
)

require (
	github.com/golang/protobuf v1.5.2 // indirect
	golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
	golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect
	golang.org/x/text v0.3.0 // indirect
	google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
)

3.2 proto

shop.proto

syntax = "proto3";// Protocol is proto3

package proto;

option go_package = "./";

// Define Send Request Information
message ProdRequest {
  int32 prod_id = 1; // Commodity ID
}

// Define response information
message ProdResponse {
  optional int32 prod_id = 1;
  repeated string prod_name = 2 ; // Commodity Name
}

// Define Services
service ProdService {
  rpc GetProd(ProdRequest) returns(ProdResponse);
}

Generate go file from proto file

protoc --go_out=plugins=grpc:./proto ./proto/shop.proto

3.3 service

ProdService.go

package service

import (
	"context"
	"fmt"
)
import . "go-study/proto"

type ProdService struct {
}

func (this *ProdService) GetProd(ctx context.Context, req *ProdRequest) (*ProdResponse, error) {
	prodId := req.GetProdId()
	fmt.Println("get--", prodId)
	prodNames := []string{"Tea with milk", "cola"}
	return &ProdResponse{ProdId: &prodId, ProdName: prodNames}, nil
}

3.4 server

server.go

package main

import (
	db "go-study/proto"
	svr "go-study/service"
	"google.golang.org/grpc"
	"log"
	"net"
)

const (
	// Address listening address
	ADDRESS string = ":8081"
	// Network Work Network Communication Protocol
	NETWORK string = "tcp"
)

func main() {
	// Listen on local ports
	lis, err := net.Listen(NETWORK, ADDRESS)
	if err != nil {
		log.Fatal("Net.Listen err: %v", err)
	}
	// New gRPC Server Instance
	server := grpc.NewServer()
	// Registration Services
	db.RegisterProdServiceServer(server, new(svr.ProdService))
	err = server.Serve(lis)
	if err != nil {
		return
	}
}

3.5 client

client.go

package main

import (
	ctx "context"
	"fmt"
	db "go-study/proto"
	"google.golang.org/grpc"
	"log"
)

const (
	// Address Connection Address
	Address string = "127.0.0.1:8081"
)

func main() {
	conn, err := grpc.Dial(Address, grpc.WithInsecure())
	//grpc.WithInsecure() Prohibit Secure Authentication Transport
	if err != nil {
		log.Fatalf("net.Connect err: %v", err)
	}
	defer conn.Close()
	// Establish gRPC connection
	client := db.NewProdServiceClient(conn)
	res, err := client.GetProd(ctx.Background(), &db.ProdRequest{ProdId: 12})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(res)
}

Keywords: Go network rpc

Added by nrg_alpha on Mon, 03 Jan 2022 11:02:59 +0200