前言:
原文鏈接。日常學習加叁,若有錯誤倦沧,歡迎指正。
一 概覽
服務(wù)定義
像許多RPC系統(tǒng)它匕,gRPC基于一個基本思想展融,定義一個服務(wù),明確規(guī)定接口的參數(shù)和返回值豫柬。默認情況下告希,gRPC使用PB作為它的接口定義語言扑浸。
service HelloService {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string greeting = 1;
}
message HelloResponse {
string reply = 1;
}
gRPC可以定義4種類型的服務(wù)方法:
- Unary RPCs: 客戶端發(fā)送一個請求給服務(wù)端,服務(wù)端返回單個響應(yīng)燕偶,就像普通函數(shù)調(diào)用那樣喝噪。
rpc SayHello(HelloRequest) returns (HelloResponse){
}
- Server streaming RPCs: 客戶端發(fā)送一個請求給服務(wù)端,并且得到了一個流去讀取一系列返回消息指么≡途澹客戶端從返回流中讀消息直到?jīng)]有消息可讀取。gRPC保證一個RPC調(diào)用里的消息順序伯诬。
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){
}
- Client streaming RPCs: 客戶端利用提供的流寫一系列消息并將它們發(fā)送給服務(wù)端晚唇。一旦客戶端完成寫消息,它將等待服務(wù)端讀取消息并回復盗似。同樣哩陕,gRPC保證一個RPC調(diào)用里的消息順序。
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {
}
- Bidirectional streaming RPCs: 客戶端服務(wù)端2方利用讀寫流發(fā)送一系列消息赫舒。這2個流操作是相互獨立的悍及,因此客戶端和服務(wù)端可以用任何順序讀寫:例如服務(wù)端可以在寫回復之前接收所有的客戶端消息;或者它可以讀一個請求消息然后寫一個回復消息号阿;或者是讀和寫的其它結(jié)合方式 并鸵。每個流的消息順序都是保留的。
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){
}
接下來我們將在RPC生命周期中詳細查看不同類型的RPC
使用API surface
從 .proto 文件的服務(wù)定義開始扔涧,gRPC提供了protocol buffer編譯器插件來生成客戶端和服務(wù)端代碼园担。gRPC用戶在客戶端調(diào)用這些API,服務(wù)端實現(xiàn)相應(yīng)的代碼枯夜。
- 服務(wù)端側(cè)弯汰,服務(wù)實現(xiàn)了服務(wù)定義的方法,并且運行一個gRPC服務(wù)去處理客戶端調(diào)用湖雹。gRPC架構(gòu)解碼請求咏闪,執(zhí)行服務(wù)方法,并且編碼服務(wù)響應(yīng)摔吏。
- 客戶端側(cè)鸽嫂,客戶端有一個本地對象stub (一些語言中被稱作client)實現(xiàn)了服務(wù)的相同的方法≌鹘玻客戶端可以僅僅調(diào)用本地對象的這些方法据某,用合適的protocal buffer消息類型封裝請求,gRPC向服務(wù)端發(fā)送這些請求并且返回服務(wù)響應(yīng)诗箍。
同步 vs 異步
同步RPC調(diào)用會在響應(yīng)到達前阻塞(這也是RPC抽象概念里最渴望的)癣籽。在另一方面,網(wǎng)絡(luò)本質(zhì)上是異步的,并且在許多場景中筷狼,不阻塞當前線程的RPC是很有用的瓶籽。
在許多語言中,gRPC編程都是同時支持同步調(diào)用和異步調(diào)用埂材。你可以在每個語言的指南中找到更多相關(guān)信息塑顺。
二 RPC生命周期
現(xiàn)在讓我們詳細看下gRPC客戶端調(diào)用gRPC服務(wù)端方法發(fā)生了什么。
Unary RPC
首先讓我們看下RPC中最簡單的類型:客戶端發(fā)送單個請求并得到單個響應(yīng)楞遏。
- 一旦客戶端調(diào)用 stub/client 對象中的方法茬暇,服務(wù)端就會被通知RPC被調(diào)用了,伴隨著服務(wù)名稱和deadline(如果被定義的話)寡喝。
- 服務(wù)端可以立即發(fā)送初始信息內(nèi)容(必須在任何回復之前發(fā)送),或者等待客戶端的請求消息勒奇。
- 一旦服務(wù)接收到了客戶端的請求消息预鬓,它將做必要的工作去創(chuàng)建和填充回復消息。如果請求處理成功赊颠,回復消息以及狀態(tài)詳情和可選的尾部元數(shù)據(jù)之后會被返回給客戶端(包含狀態(tài)碼和可選的狀態(tài)消息)格二。
- 如果status是OK, 客戶端完成了調(diào)用并得到回復竣蹦。
Server streaming RPC
server-streaming RPC和我們簡單的例子是相似的顶猜,除了服務(wù)端在得到客戶端請求消息后會返回一連串回復。在發(fā)送完所有的回復消息 痘括,服務(wù)端的狀態(tài)詳情(例如狀態(tài)碼和可選的狀態(tài)消息)以及可選的尾部元數(shù)據(jù)后长窄,服務(wù)端就完成了它的任務(wù)「倬客戶端這里一旦接收到了服務(wù)端所有的回復后就完成了調(diào)用挠日。
Client streaming RPC
client-streaming RPC和簡單例子也是相似的,除了客戶端發(fā)送給服務(wù)端的是一連串請求消息而不是單個請求消息翰舌。典型的但不是必須的嚣潜,服務(wù)端在接收到所有的客戶端請求后,返回單個回復消息椅贱,以及狀態(tài)詳細和可選的尾部元數(shù)據(jù)懂算。
Bidirectional streaming RPC
在一個bidirectional streaming RPC中,再一次的客戶端初始化調(diào)用方法庇麦,服務(wù)端接收到客戶端發(fā)送的元數(shù)據(jù)计技,方法名稱和deadline。服務(wù)可以選擇發(fā)送回初始化元數(shù)據(jù)或者等待客戶端開始發(fā)送請求女器。
接下來發(fā)生什么依賴于應(yīng)用程序酸役,客戶端和服務(wù)端可以用任意順序讀寫消息-流操作直接是完全相互獨立的。例如,服務(wù)端可以在寫回復消息之前等待直到它接收到所有的客戶端消息涣澡,或者服務(wù)端和客戶端可以 "ping-pong": 服務(wù)端獲取一個請求贱呐,然后發(fā)送 一個響應(yīng),客戶端根據(jù)回復發(fā)送另一個請求等等 入桂。
Deadlines/Timeouts
gRPC允許客戶端去定義它們愿意等一個RPC多久去完成在一個RPC被錯誤DEADLINE_EXCEEDED終止之前奄薇。在服務(wù)端,服務(wù)可以查詢?nèi)タ词欠褚粋€特定的RPC已經(jīng)超時了抗愁,或者還剩多少時間去完成RPC馁蒂。
dealine和timeout的定義方式不同語言之間是不同的。例如蜘腌,不是所有的語言都有一個默認的deadline沫屡,一些語言的APIs就deadline(一個固定的時間點)工作,一些語言的APIs就timeouts工作(時間區(qū)間)撮珠。
RPC termination
在gRPC中沮脖,客戶端和服務(wù)端有獨立的和本地的確定關(guān)于調(diào)用是否成功,并且它們的結(jié)論不一定是一致的芯急。這意味著勺届,你可以有一個RPC在服務(wù)端成功完成了(我已經(jīng)成功發(fā)送了我所有的回復),但是在客戶端失敗了(回復在我的deadline之后到達了)娶耍。這也是有可能的一個服務(wù)在客戶端發(fā)送完它所有的請求之前決定完成RPC調(diào)用 免姿。
Cancelling RPCs
客戶端和服務(wù)端都可以在任意時間取消RPC調(diào)用。一個取消立即終止RPC調(diào)用榕酒,以致不再有工作繼續(xù)執(zhí)行胚膊。它不是一個"undo": 在取消前執(zhí)行的工作不會被回滾。
Metadata
Metadata關(guān)于一個特定RPC調(diào)用的信息(例如授權(quán)詳情)奈应,它的形式是一列key-value鍵值對(key是字符串澜掩,value通常是字符串,當然也可以是二進制數(shù)據(jù))杖挣。元數(shù)據(jù)對gRPC本身是不透明的-它在調(diào)用中讓客戶端提供信息給服務(wù)端肩榕,反之也是一樣。
訪問元數(shù)據(jù)是語言相關(guān)的惩妇。
Channels
一個gRPC channel提供了一個向特定主機和端口服務(wù)的連接株汉,并且被使用當創(chuàng)建了一個client stub「柩辏客戶端可以定義channel參數(shù)去調(diào)整gRPC的默認 行為乔妈,例如開或者關(guān)消息壓縮。一個channel有狀態(tài)氓皱,包括connected和idle路召。
gRPC是如何處理關(guān)閉的channel是語言相關(guān)的勃刨。一些語言也禁止查詢channel狀態(tài) 。