gRPC 學(xué)習(xí)筆記

?gRPC 學(xué)習(xí)筆記,記錄gprc一些基本概念.

?gRPC正如其他 RPC 系統(tǒng)捧弃,gRPC 基于如下思想:定義一個服務(wù)彩掐,指定其可以被遠程調(diào)用的方法及其參數(shù)和返回類型焕数。gRPC 默認使用 protocol buffers 作為接口定義語言泽疆,來描述服務(wù)接口和有效載荷消息結(jié)構(gòu)要门。如果有需要的話,可以使用其他替代方案胚想。

gRPC是基于HTTP/2協(xié)議的,要深刻理解 gRPC協(xié)議,就有必要理解一下 HTTP/2協(xié)議.

gRPC是什么

gRPC 一開始由 google 開發(fā)琐凭,是一款語言中立芽隆、平臺中立浊服、開源的遠程過程調(diào)用(RPC)系統(tǒng).

在 gRPC 里客戶端應(yīng)用可以像調(diào)用本地對象一樣直接調(diào)用另一臺不同的機器上服務(wù)端應(yīng)用的方法,使得您能夠更容易地創(chuàng)建分布式應(yīng)用和服務(wù)胚吁。與許多 RPC 系統(tǒng)類似牙躺,gRPC 也是基于以下理念:定義一個服務(wù),指定其能夠被遠程調(diào)用的方法(包含參數(shù)和返回類型)腕扶。在服務(wù)端實現(xiàn)這個接口孽拷,并運行一個 gRPC 服務(wù)器來處理客戶端調(diào)用。在客戶端擁有一個存根能夠像服務(wù)端一樣的方法半抱。

gRPC 客戶端和服務(wù)端可以在多種環(huán)境中運行和交互 - 從 google 內(nèi)部的服務(wù)器到你自己的筆記本脓恕,并且可以用任何 gRPC 支持的語言來編寫。所以窿侈,你可以很容易地用 Java 創(chuàng)建一個 gRPC 服務(wù)端炼幔,用 Go、Python史简、Ruby 來創(chuàng)建客戶端乃秀。此外,Google 最新 API 將有 gRPC 版本的接口圆兵,使你很容易地將 Google 的功能集成到你的應(yīng)用里跺讯。

更多跨語言跨平臺支持請看這里

gRPC架構(gòu)

image

如上圖所示,gRPC 的代碼結(jié)構(gòu)主要分為三層:

  • 運輸層殉农,最低層刀脏,基于 Http2.0 和 SSL。
  • 通道層(Channel層)超凳,核心的 C 代碼愈污,實現(xiàn)與運輸層的交互。
  • 應(yīng)用層聪建,各種語言的實現(xiàn)钙畔,實現(xiàn)各種語言調(diào)用通道層的 C 代碼。

PS: gRPC 的 Java 和 Go 語言版本不由上面架構(gòu)實現(xiàn)金麸,Java 和 Go 有自己的高性能網(wǎng)絡(luò)庫擎析。

protocol buffers

gRPC 默認使用 protocol buffers,這是 Google 開源的一套成熟的結(jié)構(gòu)數(shù)據(jù)序列化機制(當(dāng)然也可以使用其他數(shù)據(jù)格式如 JSON)。你可以用 proto files 創(chuàng)建 gRPC 服務(wù)揍魂,用 protocol buffers 消息類型來定義方法參數(shù)和返回類型桨醋。

服務(wù)定義

正如其他 RPC 系統(tǒng),gRPC 基于如下思想:定義一個服務(wù)现斋, 指定其可以被遠程調(diào)用的方法及其參數(shù)和返回類型喜最。gRPC 默認使用 protocol buffers 作為接口定義語言,來描述服務(wù)接口和有效載荷消息結(jié)構(gòu)庄蹋。如果有需要的話瞬内,可以使用其他替代方案。

service HelloService {
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

message HelloRequest {
  required string greeting = 1;
}

message HelloResponse {
  required string reply = 1;
}

gRPC 允許你定義四類服務(wù)方法:

  • 單項 RPC限书,即客戶端發(fā)送一個請求給服務(wù)端虫蝶,從服務(wù)端獲取一個應(yīng)答,就像一次普通的函數(shù)調(diào)用倦西。
rpc SayHello(HelloRequest) returns (HelloResponse){
}
  • 服務(wù)端流式 RPC能真,即客戶端發(fā)送一個請求給服務(wù)端,可獲取一個數(shù)據(jù)流用來讀取一系列消息扰柠》垲恚客戶端從返回的數(shù)據(jù)流里一直讀取直到?jīng)]有更多消息為止。
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){
}
  • 客戶端流式 RPC卤档,即客戶端用提供的一個數(shù)據(jù)流寫入并發(fā)送一系列消息給服務(wù)端蝙泼。一旦客戶端完成消息寫入,就等待服務(wù)端讀取這些消息并返回應(yīng)答裆装。
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {
}
  • 雙向流式 RPC踱承,即兩邊都可以分別通過一個讀寫數(shù)據(jù)流來發(fā)送一系列消息。這兩個數(shù)據(jù)流操作是相互獨立的哨免,所以客戶端和服務(wù)端能按其希望的任意順序讀寫茎活,例如:服務(wù)端可以在寫應(yīng)答前等待所有的客戶端消息,或者它可以先讀一個消息再寫一個消息琢唾,或者是讀寫相結(jié)合的其他方式载荔。每個數(shù)據(jù)流里消息的順序會被保持。
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){
}

使用 API 接口

gRPC 提供 protocol buffer 編譯插件采桃,能夠從一個服務(wù)定義的 .proto 文件生成客戶端和服務(wù)端代碼懒熙。通常 gRPC 用戶可以在服務(wù)端實現(xiàn)這些API,并從客戶端調(diào)用它們普办。

  • 在服務(wù)側(cè)工扎,服務(wù)端實現(xiàn)服務(wù)接口,運行一個 gRPC 服務(wù)器來處理客戶端調(diào)用衔蹲。gRPC 底層架構(gòu)會解碼傳入的請求肢娘,執(zhí)行服務(wù)方法,編碼服務(wù)應(yīng)答。
  • 在客戶側(cè)橱健,客戶端有一個存根實現(xiàn)了服務(wù)端同樣的方法而钞。客戶端可以在本地存根調(diào)用這些方法拘荡,用合適的 protocol buffer 消息類型封裝這些參數(shù)— gRPC 來負責(zé)發(fā)送請求給服務(wù)端并返回服務(wù)端 protocol buffer 響應(yīng)臼节。

同步 vs 異步

同步 RPC 調(diào)用一直會阻塞直到從服務(wù)端獲得一個應(yīng)答,這與 RPC 希望的抽象最為接近珊皿。另一方面網(wǎng)絡(luò)內(nèi)部是異步的网缝,并且在許多場景下能夠在不阻塞當(dāng)前線程的情況下啟動 RPC 是非常有用的。

在多數(shù)語言里亮隙,gRPC 編程接口同時支持同步和異步的特點途凫。

RPC 生命周期

現(xiàn)在讓我們來仔細了解一下當(dāng) gRPC 客戶端調(diào)用 gRPC 服務(wù)端的方法時到底發(fā)生了什么垢夹。

單項 RPC

首先我們來了解一下最簡單的 RPC 形式:客戶端發(fā)出單個請求溢吻,獲得單個響應(yīng)。

  • 一旦客戶端通過樁調(diào)用一個方法果元,服務(wù)端會得到相關(guān)通知 促王,通知包括客戶端的元數(shù)據(jù),方法名而晒,允許的響應(yīng)期限(如果可以的話)

  • 服務(wù)端既可以在任何響應(yīng)之前直接發(fā)送回初始的元數(shù)據(jù)蝇狼,也可以等待客戶端的請求信息,到底哪個先發(fā)生倡怎,取決于具體的應(yīng)用.

  • 一旦服務(wù)端獲得客戶端的請求信息迅耘,就會做所需的任何工作來創(chuàng)建或組裝對應(yīng)的響應(yīng)。如果成功的話监署,這個響應(yīng)會和包含狀態(tài)碼以及可選的狀態(tài)信息等狀態(tài)明細及可選的追蹤信息返回給客戶端 颤专。

  • 假如狀態(tài)是 OK 的話,客戶端會得到應(yīng)答钠乏,這將結(jié)束客戶端的調(diào)用栖秕。

服務(wù)端流式 RPC

服務(wù)端流式 RPC 除了在得到客戶端請求信息后發(fā)送回一個應(yīng)答流之外,與我們的簡單例子一樣晓避。在發(fā)送完所有應(yīng)答后簇捍,服務(wù)端的狀態(tài)詳情(狀態(tài)碼和可選的狀態(tài)信息)和可選的跟蹤元數(shù)據(jù)被發(fā)送回客戶端,以此來完成服務(wù)端的工作俏拱∈钏埽客戶端在接收到所有服務(wù)端的應(yīng)答后也完成了工作。

客戶端流式 RPC

客戶端流式 RPC 也基本與我們的簡單例子一樣锅必,區(qū)別在于客戶端通過發(fā)送一個請求流給服務(wù)端事格,取代了原先發(fā)送的單個請求。服務(wù)端通常(但并不必須)會在接收到客戶端所有的請求后發(fā)送回一個應(yīng)答,其中附帶有它的狀態(tài)詳情和可選的跟蹤數(shù)據(jù)分蓖。

雙向流式 RPC

雙向流式 RPC 尔艇,調(diào)用由客戶端調(diào)用方法來初始化,而服務(wù)端則接收到客戶端的元數(shù)據(jù)么鹤,方法名和截止時間终娃。服務(wù)端可以選擇發(fā)送回它的初始元數(shù)據(jù)或等待客戶端發(fā)送請求。

下一步怎樣發(fā)展取決于應(yīng)用蒸甜,因為客戶端和服務(wù)端能在任意順序上讀寫 - 這些流的操作是完全獨立的棠耕。例如服務(wù)端可以一直等直到它接收到所有客戶端的消息才寫應(yīng)答,或者服務(wù)端和客戶端可以像"乒乓球"一樣:服務(wù)端后得到一個請求就回送一個應(yīng)答柠新,接著客戶端根據(jù)應(yīng)答來發(fā)送另一個請求窍荧,以此類推。

截止時間

gRPC 允許客戶端在調(diào)用一個遠程方法前指定一個最后期限值恨憎。這個值指定了在客戶端可以等待服務(wù)端多長時間來應(yīng)答蕊退,超過這個時間值 RPC 將結(jié)束并返回DEADLINE_EXCEEDED錯誤。在服務(wù)端可以查詢這個期限值來看是否一個特定的方法已經(jīng)過期憔恳,或者還剩多長時間來完成這個方法瓤荔。
各語言來指定一個截止時間的方式是不同的 - 比如在 Python 里一個截止時間值總是必須的,但并不是所有語言都有一個默認的截止時間钥组。

RPC 終止

在 gRPC 里输硝,客戶端和服務(wù)端對調(diào)用成功的判斷是獨立的、本地的程梦,他們的結(jié)論可能不一致点把。這意味著,比如你有一個 RPC 在服務(wù)端成功結(jié)束("我已經(jīng)返回了所有應(yīng)答!")屿附,到那時在客戶端可能是失敗的("應(yīng)答在最后期限后才來到!")郎逃。也可能在客戶端把所有請求發(fā)送完前,服務(wù)端卻判斷調(diào)用已經(jīng)完成了拿撩。

取消 RPC

無論客戶端還是服務(wù)端均可以再任何時間取消一個 RPC 衣厘。一個取消會立即終止 RPC 這樣可以避免更多操作被執(zhí)行。它不是一個"撤銷"压恒, 在取消前已經(jīng)完成的不會被回滾影暴。當(dāng)然,通過同步調(diào)用的 RPC 不能被取消探赫,因為直到 RPC 結(jié)束前型宙,程序控制權(quán)還沒有交還給應(yīng)用。

元數(shù)據(jù)集

元數(shù)據(jù)是一個特殊 RPC 調(diào)用對應(yīng)的信息(授權(quán)詳情]) 伦吠,這些信息以鍵值對的形式存在妆兑,一般鍵的類型是字符串魂拦,值的類型一般也是字符串(當(dāng)然也可以是二進制數(shù)據(jù))。元數(shù)據(jù)對 gRPC 本事來說是不透明的 - 它讓客戶端提供調(diào)用相關(guān)的信息給服務(wù)端搁嗓,反之亦然芯勘。

對于元數(shù)據(jù)的訪問是語言相關(guān)的。

channel

在創(chuàng)建客戶端存根時腺逛,一個 gRPC channel 提供一個特定主機和端口服務(wù)端的連接荷愕。客戶端可以通過指定 channel 參數(shù)來修改 gRPC 的默認行為棍矛,比如打開關(guān)閉消息壓縮安疗。一個 chennel 具有狀態(tài),包含已連接和空閑 够委。

gRPC 如何處理關(guān)閉 channel 是語言相關(guān)的荐类。有些語言可允許詢問頻道狀態(tài)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末茁帽,一起剝皮案震驚了整個濱河市玉罐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌脐雪,老刑警劉巖厌小,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異战秋,居然都是意外死亡,警方通過查閱死者的電腦和手機讨韭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門脂信,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人透硝,你說我怎么就攤上這事狰闪。” “怎么了濒生?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵埋泵,是天一觀的道長。 經(jīng)常有香客問我罪治,道長丽声,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任觉义,我火速辦了婚禮雁社,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘晒骇。我一直安慰自己霉撵,他們只是感情好磺浙,可當(dāng)我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著徒坡,像睡著了一般撕氧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上喇完,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天呵曹,我揣著相機與錄音,去河邊找鬼何暮。 笑死奄喂,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的海洼。 我是一名探鬼主播跨新,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼坏逢!你這毒婦竟也來了域帐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤是整,失蹤者是張志新(化名)和其女友劉穎肖揣,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浮入,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡龙优,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了事秀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片彤断。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖易迹,靈堂內(nèi)的尸體忽然破棺而出宰衙,到底是詐尸還是另有隱情,我是刑警寧澤睹欲,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布供炼,位于F島的核電站,受9級特大地震影響窘疮,放射性物質(zhì)發(fā)生泄漏袋哼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一考余、第九天 我趴在偏房一處隱蔽的房頂上張望先嬉。 院中可真熱鬧,春花似錦楚堤、人聲如沸疫蔓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽衅胀。三九已至岔乔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間滚躯,已是汗流浹背雏门。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留掸掏,地道東北人茁影。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像丧凤,于是被迫代替她去往敵國和親募闲。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容