Grpc introduction

Time:2022-5-25

[TOC]

gRPC

Grpc introduction

What is grpc?

What is the difference between RPC and restful?

RPC message transmission can be TCP, UDP or http. When RPC message transmission is HTTP, its structure is similar to restful architecture

What is the difference between RPC and restful:

  • Restful will be more flexible if the objects of operation are different

RPC operates on method objects and restful operates on resources

The client and server of RPC are tightly coupled. The client needs to know the function name, parameter type and order of the server in order to call the remote procedure.

Restful semantic operation resources based on HTTP, and the order of parameters is generally irrelevant

  • RCP is more suitable for customization

    Restful performs operations on resources, mainly curd (addition, deletion, modification and query). If it is necessary to implement a specific function, such as calculating the average score of a class, it is more meaningful to use the method of RPC defining the server (such as stu. Calavg) for the client to call

What are the characteristics of grpc?

  • Grpc can be developed across languages

The grpc client can directly call remote programs on different servers. Using gestures looks like calling local procedure calls. It is easy to build distributed applications and services. The client and server can be implemented in different languages supported by grpc.

  • Based on the http2 standard design, there are some advantages over other frameworks

    • supportLong connection, bidirectional flow, header compression, multiple multiplexing requestsetc.
    • Save bandwidthReduce the number of TCP linksSave CPU usageandExtend battery life
    • Improve the performance of cloud services and web applications
    • The interaction between client and server is transparent
    • Grpc uses protobuf by default to serialize data

What is the data interaction mode of grpc?

Request response

The client sends a request and can read a series of messages from the server

The client writes a series of messages to the server and waits for the server to respond

Both client and server can send a series of messages by reading and writing data streams

Data serialization method – protobuf

Protobuf is a way to serialize data, such as JSON, XML, etc

This paper briefly introduces the three keywords contained in the structure definition of protobuf

  • With Proto is used as the suffix, and the statements except the structure definition end with a semicolon
  • Structure definitions can include:message、service、enum, three keywords
  • Semicolon at the end of RPC method definition is optional

MessageNaming adoptionHump naming method, fields are lowercase and underlined

 message ServerRequest {
      required string my_name = 1;
  }

EnumsThe type name adopts hump naming method, and the field name adopts uppercase letters and underline

 enum MyNum {
      VALUE1 = 1;
      VALUE2 = 2;
  }

Service and RPC method namesUnified adoptionHump naming

service Love {
  //Define the conference method
  rpc MyConfession(Request) returns (Response) {}
}

For the installation of prtobuf, please refer to an installation step written before《5 steps to complete the installation of protobuf

Use in proto filespackageKeyword declares the package name. By default, it is converted to the package name in go, which is consistent with this. You can customize the package name and modify itgo_packageYou can:

test.proto

syntax = "proto3"; //  Proto version

package pb; //  Specify the package name, which is also the package name in the default go

//Define love service
service Love {
  //Define the conference method
  rpc Confession(Request) returns (Response) {}
}

//Request
message Request {
  string name = 1;
}

//Respond
message Response {
  string result = 1;
}

After installing the protoc environment, enter the directory of the proto file (for example, open thewindow git)Execute the following command toprotoFile compiled intopb.gofile

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

Conversion result:

// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
//     protoc-gen-go v1.25.0
//     protoc        v3.13.0
// source: test.proto

package test

import (
    context "context"
    proto "github.com/golang/protobuf/proto"
    grpc "google.golang.org/grpc"
    codes "google.golang.org/grpc/codes"
    status "google.golang.org/grpc/status"
    protoreflect "google.golang.org/protobuf/reflect/protoreflect"
    protoimpl "google.golang.org/protobuf/runtime/protoimpl"
    reflect "reflect"
    sync "sync"
)

const (
    // Verify that this generated code is sufficiently up-to-date.
    _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
    // Verify that runtime/protoimpl is sufficiently up-to-date.
    _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4

type Request struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields

    Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
}


type Response struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields

    Result string `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"`
}

// LoveServer is the server API for Love service.
type LoveServer interface {
    Confession(context.Context, *Request) (*Response, error)
}

A demo

The directory structure is:


-------------------------------
| mygrpc
| ---------pb
| -------------test.proto
| ---------client.go
| ---------srv.go
-------------------------------

client.go

package main

import (
    "context"
    "log"

    "mygrpc.com/pb"

    "google.golang.org/grpc"
)

func main() {
    //Connect to grpc service
    conn, err := grpc.Dial(":8888", grpc.WithInsecure())
    if err != nil {
        log.Fatal(err)
    }
    //Very critical
    defer conn.Close()

    //Initialize client
    c := pb.NewLoveClient(conn)

    //Initiate request
    response, err := c.Confession(context.Background(), &pb. Request {Name: "Little Devil boy Nezha"})
    if err != nil {
        log.Fatal(err)
    }

    log.Println(response.Result)
}

server.go

package main

import (
    "context"
    "log"
    "net"

    "google.golang.org/grpc"
    "mygrpc.com/pb"
)

//Define love service
type Love struct {
}

//Implement the love service interface
func (l *Love) Confession(ctx context.Context, request *pb.Request) (*pb.Response, error) {
    resp := &pb.Response{}
    resp.Result = "your name is " + request.Name
    return resp, nil
}

func main() {
    //Listen to port 8888
    listen, err := net.Listen("tcp", ":8888")
    if err != nil {
        log.Fatal(err)
    }

    //Instantiate grpc server
    s := grpc.NewServer()

    //Register for love service
    pb.RegisterLoveServer(s, new(Love))

    log.Println("Listen on 127.0.0.1:8888...")
    s.Serve(listen)
}

Next, we will introduce the authentication of grpc

Technology is open, and our mentality should be open. Embrace change, grow into the sun and strive to move forward.

I’m Nezha, the Little Devil boy. Welcome to praise and pay attention to the collection. See you next time~