gRPC介紹

[TOC]git

gRPC

gRPC介紹

gRPC是什麼?

RPC和RESTful的區別是什麼?

RPC的消息傳輸能夠是TCP,能夠是UDP,也能夠是HTTP,當RPC消息傳輸是HTTP時,它的結構與RESTful的架構相似github

RPC和RESTful有什麼不一樣呢:golang

  • 操做的對象不同的,RESTful會更加靈活

RPC操做的是方法對象, RESTful操做的是資源json

RPC的客戶端和服務器端是緊耦合的,客戶端須要知道服務端的函數名字,參數類型、順序等,才能遠程過程調用。bash

RESTful基於 http的語義操做資源,參數的順序通常沒有關係服務器

  • RCP更適合定製化架構

    RESTful執行的是對資源的操做,主要都是CURD(增刪改查)的操做,若須要實現一個特定的功能,如計算一個班級的平均分,這個時候使用RPC定義服務器的方法(如:Stu.CalAvg)供客戶端調用則顯得更有意義框架

gRPC的特性是什麼?

  • gRPC是能夠跨語言開發的

在gRPC客戶端能夠直接調用不一樣服務器上的遠程程序,使用姿式看起來就像調用本地過程調用同樣,很容易去構建分佈式應用和服務。客戶端和服務端能夠分別使用gRPC支持的不一樣語言實現。tcp

  • 基於HTTP2標準設計,比其餘框架更優的地方有分佈式

    • 支持長鏈接,雙向流、頭部壓縮、多複用請求
    • 節省帶寬下降TCP連接次數節省CPU使用延長電池壽命
    • 提升了雲端服務和Web應用的性能
    • 客戶端和服務端交互透明
    • gRPC默認使用protobuf來對數據序列化

gRPC的數據交互模式是怎麼樣的?

請求應答式

客戶端發出一次請求,能夠從服務端讀取一系列的消息

客戶端寫一系列消息給到服務端,等待服務端應答

客戶端和服務端均可以經過讀寫數據流來發送一系列消息

數據的序列化方式 - protobuf

protobuf 是一個對數據序列化的方式,相似的有JSON,XML等

簡單介紹protobuf的結構定義包含的3個關鍵字

  • 以.proto作爲後綴,除結構定義外的語句以分號結尾
  • 結構定義能夠包含:message、service、enum,三個關鍵字
  • rpc方法定義結尾的分號無關緊要

Message命名採用駝峯命名方式,字段是小寫加下劃線

message ServerRequest {
      required string my_name = 1;
  }

Enums類型名採用駝峯命名方式,字段命名採用大寫字母加下劃線

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

Service與rpc方法名統一採用駝峯式命名

service Love {
  // 定義Confession方法
  rpc MyConfession(Request) returns (Response) {}
}

關於prtobuf的安裝能夠看看以前寫的一個安裝步驟《5個步驟搞定PROTOBUF的安裝

在proto文件中使用package關鍵字聲明包名,默認轉換成go中的包名與此一致,能夠自定義包名,修改go_package便可:

test.proto

syntax = "proto3"; // proto版本

package pb; // 指定包名,默認go中包名也是這個

// 定義Love服務
service Love {
  // 定義Confession方法
  rpc Confession(Request) returns (Response) {}
}

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

// 響應
message Response {
  string result = 1;
}

安裝好protoc環境以後,進入到proto文件的目錄下,(例如打開window git)執行以下命令,將proto文件編譯成pb.go文件

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

轉換結果:

// 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)
}

一個DEMO

目錄結構爲:

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

client.go

package main

import (
    "context"
    "log"

    "mygrpc.com/pb"

    "google.golang.org/grpc"
)

func main() {
    // 鏈接grpc服務
    conn, err := grpc.Dial(":8888", grpc.WithInsecure())
    if err != nil {
        log.Fatal(err)
    }
    // 很關鍵
    defer conn.Close()

    // 初始化客戶端
    c := pb.NewLoveClient(conn)

    // 發起請求
    response, err := c.Confession(context.Background(), &pb.Request{Name: "小魔童哪吒"})
    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"
)

// 定義Love服務
type Love struct {
}

// 實現Love服務接口
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() {
    // 監聽8888端口
    listen, err := net.Listen("tcp", ":8888")
    if err != nil {
        log.Fatal(err)
    }

    // 實例化grpc server
    s := grpc.NewServer()

    // 註冊Love服務
    pb.RegisterLoveServer(s, new(Love))

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

下一次介紹關於gRPC的認證

技術是開放的,咱們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。

我是小魔童哪吒,歡迎點贊關注收藏,下次見~

相關文章
相關標籤/搜索