2022-10-04 分類: 網(wǎng)站建設(shè)
介紹
我猜測(cè)大部分長期使用 Java 的開發(fā)者應(yīng)該較少會(huì)接觸 gRPC,畢竟在 Java 圈子里大部分使用的還是 Dubbo/SpringClound 這兩類服務(wù)框架。
我也是近段時(shí)間有機(jī)會(huì)從零開始重構(gòu)業(yè)務(wù)才接觸到 gRPC 的,當(dāng)時(shí)選擇gRPC 時(shí)也有幾個(gè)原因:
基于云原生的思路開發(fā)部署項(xiàng)目,而在云原生中 gRPC 幾乎已經(jīng)是標(biāo)準(zhǔn)的通訊協(xié)議了。 開發(fā)語言選擇了 Go,在 Go 圈子中 gRPC 顯然是更好的選擇。 公司內(nèi)部有部分業(yè)務(wù)使用的是 Python 開發(fā),在多語言兼容性上 gRPC 支持的非常好。
經(jīng)過線上一年多的平穩(wěn)運(yùn)行,可以看出 gRPC 還是非常穩(wěn)定高效的;rpc 框架中最核心的幾個(gè)要點(diǎn):序列化 通信協(xié)議 IDL(接口描述語言)
這些在 gRPC 中分別對(duì)應(yīng)的是: 基于 Protocol Buffer 序列化協(xié)議,性能高效。 基于 HTTP/2 標(biāo)準(zhǔn)協(xié)議開發(fā),自帶 stream、多路復(fù)用等特性;同時(shí)由于是標(biāo)準(zhǔn)協(xié)議,第三方工具的兼容性會(huì)更好(比如負(fù)載均衡、監(jiān)控等)。編寫一份 .proto 接口文件,便可生成常用語言代碼。 HTTP/2
學(xué)習(xí) gRPC 之前首先得知道它是通過什么協(xié)議通信的,我們?nèi)粘2还苁情_發(fā)還是應(yīng)用基本上接觸到最多的還是 HTTP/1.1 協(xié)議。
由于 HTTP/1.1 是一個(gè)文本協(xié)議,對(duì)人類非常友好,相反的對(duì)機(jī)器性能就比較低。
需要反復(fù)對(duì)文本進(jìn)行解析,效率自然就低了;要對(duì)機(jī)器更友好就得采用二進(jìn)制,HTTP/2 自然做到了。
除此之外還有其他優(yōu)點(diǎn): 多路復(fù)用:可以并行的收發(fā)消息,互不影響。HPACK 節(jié)省 header 空間,避免 HTTP1.1 對(duì)相同的 header 反復(fù)發(fā)送。 Protocol
gRPC 采用的是 Protocol 序列化,發(fā)布時(shí)間比 gRPC 早一些,所以也不僅只用于 gRPC,任何需要序列化 IO 操作的場(chǎng)景都可以使用它。
它會(huì)更加的省空間、高性能;之前在開發(fā) https://github.com/crossoverJie/cim 時(shí)就使用它來做數(shù)據(jù)交互。package order.v1; service OrderService{ rpc Create(OrderApiCreate) returns (Order) {} rpc Close(CloseApiCreate) returns (Order) {} // 服務(wù)端推送 rpc ServerStream(OrderApiCreate) returns (stream Order) {} // 客戶端推送 rpc ClientStream(stream OrderApiCreate) returns (Order) {} // 雙向推送 rpc BdStream(stream OrderApiCreate) returns (stream Order) {} } message OrderApiCreate{ int64 order_id = 1; repeated int64 user_id = 2; string remark = 3; repeated int32 reason_id = 4; }使用起來也是非常簡單的,只需要定義自己的 .proto 文件,便可用命令行工具生成對(duì)應(yīng)語言的 SDK。
具體可以參考官方文檔:https://grpc.io/docs/languages/go/generated-code/ 調(diào)用 protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ test.proto 生成代碼之后編寫服務(wù)端就非常簡單了,只需要實(shí)現(xiàn)生成的接口即可。func (o *Order) Create(ctx context.Context, in *v1.OrderApiCreate) (*v1.Order, error) { // 獲取 metadata md, ok := metadata.FromIncomingContext(ctx) if !ok { return nil, status.Errorf(codes.DataLoss, "failed to get metadata") } fmt.Println(md) fmt.Println(in.OrderId) return &v1.Order{ OrderId: in.OrderId, Reason: nil, }, nil }客戶端也非常簡單,只需要依賴服務(wù)端代碼,創(chuàng)建一個(gè) connection 然后就和調(diào)用本地方法一樣了。
這是經(jīng)典的 unary(一元)調(diào)用,類似于 http 的請(qǐng)求響應(yīng)模式,一個(gè)請(qǐng)求對(duì)應(yīng)一次響應(yīng)。
Server stream
gRPC 除了常規(guī)的 unary 調(diào)用之外還支持服務(wù)端推送,在一些特定場(chǎng)景下還是很有用的。
func (o *Order) ServerStream(in *v1.OrderApiCreate, rs v1.OrderService_ServerStreamServer) error { for i := 0; i < 5; i++ { rs.Send(&v1.Order{ OrderId: in.OrderId, Reason: nil, }) } return nil } 服務(wù)端的推送如上所示,調(diào)用 Send 函數(shù)便可向客戶端推送。 for { msg, err := rpc.RecvMsg() if err == io.EOF { marshalIndent, _ := json.MarshalIndent(msgs, "", "\t") fmt.Println(msg) return } }客戶端則通過一個(gè)循環(huán)判斷當(dāng)前接收到的數(shù)據(jù)包是否已經(jīng)截止來獲取服務(wù)端消息。
為了能更直觀的展示這個(gè)過程,優(yōu)化了之前開發(fā)的一個(gè) gRPC 客戶端,可以直觀的調(diào)試 stream 調(diào)用。
上圖便是一個(gè)服務(wù)端推送示例。Client Stream
除了支持服務(wù)端推送之外,客戶端也支持。
客戶端在同一個(gè)連接中一直向服務(wù)端發(fā)送數(shù)據(jù),服務(wù)端可以并行處理消息。// 服務(wù)端代碼func (o *Order) ClientStream(rs v1.OrderService_ClientStreamServer) error { var value []int64 for { recv, err := rs.Recv() if err == io.EOF { rs.SendAndClose(&v1.Order{ OrderId: 100, Reason: nil, }) log.Println(value) return nil } value = append(value, recv.OrderId) log.Printf("ClientStream receiv msg %v", recv.OrderId) } log.Println("ClientStream finish") return nil } // 客戶端代碼 for i := 0; i < 5; i++ { messages, _ := GetMsg(data) rpc.SendMsg(messages[0]) } receive, err := rpc.CloseAndReceive()代碼與服務(wù)端推送類似,只是角色互換了。
Bidirectional Stream
同理,當(dāng)客戶端、服務(wù)端同時(shí)都在發(fā)送消息也是支持的。// 服務(wù)端func (o *Order) BdStream(rs v1.OrderService_BdStreamServer) error { var value []int64 for { recv, err := rs.Recv() if err == io.EOF { log.Println(value) return nil } if err != nil { panic(err) } value = append(value, recv.OrderId) log.Printf("BdStream receiv msg %v", recv.OrderId)
分享名稱:五分鐘學(xué)會(huì)gRPC,你學(xué)會(huì)了嗎?
鏈接分享:http://www.rwnh.cn/news28/201728.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、動(dòng)態(tài)網(wǎng)站、手機(jī)網(wǎng)站建設(shè)、電子商務(wù)、服務(wù)器托管、建站公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容