前言
grpc是一個高效能、通用的開源RPC框架,基於HTTP/2協議標準和Protobuf序列化協議開發,支援眾多的開發語言。在對介面具有嚴格約束或者傳遞大量資料的場景中得到了廣泛的應用。本文作者從什麼是grpc開始介紹,講訴了protobuf的語法以及如何使用grpc框架,對於想學習grpc的初學者來說,是一篇極好的入門教程,下來就跟隨作者一起學習吧。
簡介
什麼是grpc
grpc是一個由google推出的、高效能、開源、通用的rpc框架。它是基於HTTP2協議標準設計開發,預設採用Protocol Buffers資料序列化協議,支援多種開發語言。
什麼是protobuf buffers
ProtoBuf buffer 是一種資料表達方式,以。proto結尾的資料檔案,可以類比json、xml等。針對ProtoBuf buffer 資料來源,可以利用protoc 工具來生成各種語言的訪問類。
其操作步驟:
定義資料元;
生成資料元的訪問類。
優點:
編解碼速度更快;
傳輸的資料更小。
protobuf buffers定義資料元的語法
一個。proto檔案,主要包括以下部分:
syntax = “proto3”;package studentpb;service Student { rpc add (StudentReqs) returns (StudentReply) {} //新增學生介面}message StudentReqs { repeated StudentReq s = 1;}message StudentReq{ string name= 1; int32 age = 2;}message StudentReply { int32 errno = 1; string errmsg = 2;}
關鍵字syntax:指定使用的proto3語法;
關鍵字package:定義一個包,需要注意避免命名衝突;
關鍵字message來定義請求或相應需要使用的訊息格式,裡面可以包含了不同型別的欄位 。一個。proto檔案中,可以包含多個message的定義。
關鍵字server來定一個服務。GRPC的服務是透過引數和返回型別來指定可以遠端呼叫的方法。
欄位的約束規則
repeated:前置repeated關鍵詞,宣告該欄位為陣列型別。
proto3不支援proto2中的required和optional關鍵字。
欄位支援的型別
支援基礎型別、列舉型別、map型別、陣列型別、message型別等。
基礎型別
列舉型別
syntax = “proto3”;message Student{ string name = 1; // 定義enum型別 enum Sex { BOY = 0; GIRL = 1; } Sex sex = 1; // 使用Corpus作為欄位型別}
message型別
syntax = “proto3”;message Students { repeated Student s = 1;}message Student{ string name = 1; // 定義enum型別 enum Sex { BOY = 0; GIRL = 1; } Sex sex = 4; // 使用Corpus作為欄位型別}
如何利用protoc 工具生成訪問類
prooc常用引數
案例
檔案目錄如下:
其中“t。proto”內容如下:
syntax = “proto3”;package studentpb;service Student { rpc add (StudentReqs) returns (StudentReply) {} //新增學生介面}message StudentReqs { repeated StudentReq s = 1;}message StudentReq{ string name= 1; int32 age = 2;}message StudentReply { int32 errno = 1; string errmsg = 2;}
生成go訪問類的語句如下:
protoc ——go_out=plugins=grpc:。 protobuf/*。proto
GO如何利用GRPC通訊
pb檔案
syntax = “proto3”;package studentpb;service Student { rpc add (StudentReqs) returns (StudentReply) {} //新增學生介面}message StudentReqs { repeated StudentReq s = 1;}message StudentReq{ string name= 1; int32 age = 2;}message StudentReply { int32 errno = 1; string errmsg = 2;}
執行如下命令,生成grpc訪問類
protoc ——go_out=plugins=grpc:。 *。proto
服務端
目錄結構如下:
main。go內容如下:
package mainimport ( “context” “fmt” “google。golang。org/grpc” “log” “net” “test/studentpb”)type Student struct {}// 新增studentsfunc (r *Student) Add(ctx context。Context, in *studentpb。StudentReqs) (*studentpb。StudentReply, error) { return &studentpb。StudentReply{ Errno: 0, Errmsg: “ok”, }, nil}func main() { // 建立server監聽 rpcAddr := “127。0。0。1:8601” server, err := net。Listen(“tcp”, rpcAddr) if err != nil { fmt。Println(“failed to listen”, rpcAddr) panic(err) } // 建立rpc server var RpcServer = grpc。NewServer() err = RpcServer。Serve(server) if err != nil { log。Fatalf(“failed to listen: %v”, err) } // 對外提供服務 r := new(Student) studentpb。RegisterStudentServer(RpcServer, r) select { }}
使用者端
目錄結構如下:
package mainimport ( “context” “fmt” “google。golang。org/grpc” “test/studentpb” “time”)func main() { addr := “127。0。0。1:8601” timeout := 10 //建立rpc通道 client, err := grpc。Dial(addr, grpc。WithInsecure()) if err != nil { panic(“連線失敗”) } defer client。Close() // 建立studentrpc物件 rpcClient := studentpb。NewStudentClient(client) // 建立上線文 ctx, cancel := context。WithTimeout(context。Background(), time。Duration(timeout)*time。Second) defer cancel() //封裝請求引數 req := &studentpb。StudentReqs{} req。S = append(req。S, &studentpb。StudentReq{Name:“張三”, Age:12}) // 列印結果 res , err := rpcClient。Add(ctx, req) if err != nil { fmt。Println(“請求錯誤”, err) } else { fmt。Println(res。GetErrno(), res。GetErrmsg()) }}
關於360技術:360技術是360技術團隊打造的技術分享公眾號,每天推送技術乾貨內容,更多技術資訊歡迎關注“360技術”微信公眾號