gRPC實戰包含一系列文章,包括原創和翻譯。最終會形成一個完整的系列,後續會不斷完善,增加新的內容:
- gRPC簡介:why,what,how?
- gRPC服務健康檢查最佳實踐
- Kubernetes中使用envoy負載均衡gRPC流量
- 用Golang編寫通過gRPC進行通信的服務
- 如何在NodeJS中有效使用gRPC流
=============================================================
Why gRPC?
讓我們從一個簡單的問題開始:gRPC的動機是什麼?或是gRPC試圖解決的問題是什麼?
好吧,答案是通信。
應用程序是使用不同的編程語言編寫的。
例如,後端可以用Go編寫,而前端(例如android app用Java編寫,iOS app用Swift編寫)。
那麼他們如何互相通信
當今的趨勢是使用微服務架構。因此,即使在後端,根據業務需求和技術約束,我們可能還會有許多用不同語言(例如Go,Python或Rust)編寫的服務。
使用gRPC的動機:不同語言之間通信
- 前後端採用了不同的語言
- 微服務架構,採用了不同的語言
-
通過遵守一致的約定去交互信息
- 通信通道:REST,SOAP,消息隊列
- 身份驗證機制:Basic,OAuth,JWT
- 負載類型:JSON,XML,binary
- 數據模型
- 錯誤處理
因此,為了彼此通信,他們必須都遵守一組API約定。例如:通信通道,身份驗證機制,有效載荷格式,數據模型以及如何處理錯誤。
有太多事情需要考慮,這就是為什麼構建API真的很困難。
使用gRPC的動機:簡單而高效的通信
更重要的是,我們希望通信高效,快速且輕巧。您知道,微服務之間的交換消息數量巨大。因此,通信越快越好。
另外,在某些環境(例如移動應用)中,網絡速度和帶寬受到限制,擁有輕量級的通信協議與服務器進行交互非常重要。
最後但並非最不重要的一點是,我們希望溝通很簡單。假設我們正在構建一個包含數百個甚至數千個微服務的系統。我們絕對不希望將大部分時間花在編寫代碼上只是為了讓他們彼此通信,對嗎?
我們想要的是某種框架,允許開發人員專注於實現其服務的核心邏輯。並將其他所有內容留給框架處理。
該框架就是gRPC。
What is gRPC? How it works?
gRPC是最初由Google開發的高性能,開源,功能豐富的RPC框架,現在與Kubernetes或Prometheus一樣,它是雲原生計算基礎(或CNCF)的一部分。
RPC是什麼? RPC代表遠程過程調用。它是允許程序執行位於其他計算機上的另一個程序的過程的協議。
令人敬畏的是,開發人員不必明確編碼網絡交互的細節。它由基礎框架自動處理。
因此,在客户端代碼中,看起來我們只是在直接調用服務器代碼的功能。即使客户端和服務器上的代碼是用不同的編程語言編寫的,它也可以工作。像本示例一樣,客户端代碼用Go編寫,服務器代碼用Rust編寫。
那麼gRPC如何做到這一點?基本上,客户端具有一個存根,該存根提供與服務器相同的方法(或功能)。該存根由gRPC自動為您生成。
存根將在後台調用gRPC框架,以通過網絡與服務器交換信息。
瞧,神奇的是一切正常。由於存根,客户端和服務器現在只需要關心實現其核心服務邏輯。
接下來,我們將看到如何在protocol buffer的幫助下生成gRPC存根。
gRPC如何生成代碼?
代碼生成是gRPC的最重要功能之一。
為了為服務器和客户端生成存根,我們首先需要編寫API協定,該協定包括在protocol buffer文件中的服務及其有效載荷消息的描述,如下所示:
syntax = "proto3"
message HelloRequest {
string name = 1;
}
message HelloResponse {
string greet = 1;
}
service HelloService {
rpc Hello(HelloRequest) return (HelloResponse);
}
在此文件中,定義了一個Hello方法,該方法將HelloRequest作為輸入並返回HelloResponse。 HelloRequest僅包含一個字符串名稱,而HelloResponse具有一個字符串。
protocol buffer編譯器從此proto文件生成服務器和客户端存根代碼。根據編程語言,我們將不得不告訴編譯器為其使用正確的gRPC插件。
為Rust和Go生成的代碼將如下所示:
OK,所以您可能想知道為什麼gRPC使用protocol buffer?好吧,有很多原因。
首先,它非常易於閲讀和理解。
其次,它的語言可與多種語言自動生成代碼互操作
第三,它表示二進制格式的數據,與某些基於文本的格式(如JSON或XML)相比,它的大小更小,傳輸速度更快,序列化的效率更高。
它在客户端和服務器之間提供了一種強類型的API契約,使用它非常安全, 而且確保向後和向前的兼容性。
聽起來很棒,對嗎?但是,使用gRPC一定需要protocol buffer嗎?
答案是不。您可以改用Google Flatbuffers或Microsoft Bond。但是我認為protocol buffer已經是一個不錯的選擇。
它支持許多流行的編程語言,其中10種已正式支持,其中純實現了Go,Java,NodeJS,另外7種是gRPC核心C的包裝,即C ++,C#,Objective-C,Python,Ruby,Dart和PHP。
此外,還有許多其他語言的非官方庫,例如Swift,Rust,TypeScript,Haskell等。
gRPC與HTTP2
gRPC使用HTTP/2作為其傳輸協議,因此它繼承了HTTP/2提供的一些出色功能,例如二進制幀,與其他基於文本的協議相比,它具有高性能,強健性,更輕便的傳輸和更安全的解碼能力。而且因為它是二進制文件,所以它與protocol buffer完美結合。
HTTP/2還使用HPACK壓縮報頭,這將減少開銷成本並提高性能。
在HTTP/2中可以進行多路複用,這意味着客户端和服務器可以通過單個TCP連接並行發送多個請求和響應。這將有助於減少延遲並提高網絡利用率。
最後,HTTP/2允許服務器推送,其中來自客户端的1個單個請求使服務器可以發回多個響應。在許多情況下,當服務器確切知道客户端需要什麼資源並在請求之前將其發送時,這對於減少客户端和服務器之間的往返延遲非常有價值。