Golang基礎第五篇——golang的gRPC

此篇的組織架構,第一節簡述golang的rpc,第二節講主體golang/grpc,第三節簡述grpc應用的結構和特性。本身grpc是個上限很高的框架,這裏的博文只科普,儘量簡單地告訴你它做了什麼,有什麼用;關於使用,部署,以及更深層的原理還要自己發掘。

目錄

一,RPC編程

二,gRPC

三,grpc結構與特性


一,RPC編程

RPC是什麼?

 RPC(Remote Procedure Call) 遠程過程調用,是一種通過網絡從遠程計算機程序上請求服務,而你自己不需要了解底層網絡細節的應用程序通信協議,與之對應的是本地過程調用,即自己調用自己計算機上的服務。RPC是一種服務器-客戶端(Client/Server)模式,經典實現是一個通過發送請求-接受迴應進行信息交互的系統,通常構建於TCP,UDP或者HTTP之上,使用時開發者無需爲這個調用過程額外編寫網絡通信相關代碼,RPC框架已經爲你封裝好了。

golang的RPC

go語言原生對RPC的支持和處理實現在net/rpc包,服務端通常通過TCP或HTTP在某個網絡地址上創建服務並監聽RPC客戶端傳入的參數,客戶端通過rpc.Dial()和rpc.DialHTTP()方法來和制定的服務端創建連接,接受到處理結果之後通過Call()同步處理信息,go()異步處理信息。而且,golang還提供了序列化數據結構和編碼解碼的工具Gob,在內置的encoding/gob中,可以讓其他語言實現的客戶端都可以和go語言編寫的服務端通信。

關於RPC要解決的幾個常見問題就是分佈式以及大數據需要面對的基本問題:數據序列化,負載均衡,服務註冊,緩存更新,異步調用等,其中現在普遍更受歡迎的是gRPC。入手之後覺得grpc本身框架是優質的,不像某乎第一看待grpc的答案,剪裁的東西本身就是應該剪裁併自己造輪子的,grpc內部維護很不錯了,本意是希望你能自定義其他部分爲自己所用,其他開銷只能說每個廠情況不同,使用框架見仁見智。

二,gRPC

gRPC全稱是google Remote Procedure Call,不過golang也是google發明的,gRPC由golang編寫,所以這篇blog講的grpc指的都是grpc go。然而gRPC和傳統的RPC有什麼不同?

gRPC 是一個高性能、開源和通用的 RPC 框架,面向移動和 HTTP/2 設計。gRPC 基於 HTTP/2 標準設計,帶來諸如雙向流、流控、頭部壓縮、單 TCP 連接上的多複用請求等特性。這些特性使得其在移動設備上表現更好,更省電和節省空間佔用。

具體grpc作用的結構如下圖,數據從我們的操作系統發出到protobuf解編碼,grpc設計遠程調用後用http/2做應用信息包裝,轉至tls加密傳輸層tcp發出。

                           fig.1 grpc protocol stack

gPRC和上層Protobuf
 服務接口和傳遞的消息均以protobuf的IDL語言統一描述:分別以service和message對象表示。protoc支持插件,grpc就是通過grpc插件來實現用protoc生成client和server的代碼。client的代碼被稱爲stub。server端的主要代碼實際上是一個接口。用戶需要自己提供一個類,實現該接口,啓動server時把這個類註冊成這個服務的實現類。即protobuf負責數據的定義,編譯生成grpc可識別的IDL。

                            fig.2  grpc and protobuf

gRPC與下層Http2
gRPC是基於Http2協議的。gRPC繼承了大量Http2協議的概念和特性。
Http2中grpc客戶端和grpc服務器端一般只建立一個連接,在一個連接中可以並行地發起很多個http請求,每個請求使用一個stream來收發數據。服務器端可以主動創建stream向客戶端推送數據。
Http2的請求/響應數據均以二進制方法傳輸,且數據被組織爲frame(類似於tcp中的packet)。這樣可以允許多個請求並行地進行收發數據。gRPC中的一個channel可對應於Http2中的一個連接,而一個RPC調用對應Http2中的一個Stream。
同時Http2可以支持傳輸層加密和認證(TLS)。顯然,gRPC的加密和認證機制也可以直接利用之。

                                                    fig.3 Http/2 connection in grpc

gRPC內置的認證和加密機制
gRPC支持Transport Credential和PerRPC credential。前者顧名思義,是用於“傳輸層”的,即建立channel的時候所使用的credential,目前支持的都是TLS這種類型的機制。而後者則一般是指token這種類型的信息,每次RPC調用時都會發送,用於在服務器端認證調用者的身份並進行細粒度的權限控制。
後者一般使用interceptor進行處理,在server啓動時註冊一個interceptor。每次rpc調用時,在interceptor從客戶端發送的metadata中讀取token信息進行認證。
注意,grpc調用是否已經結束的結論是客戶端和服務器端各自獨立做出的。

 

三,grpc結構與特性

由於grpc很好的解決了rpc中的常見問題,所以被廣泛使用,這裏挑選其中的兩個特性做簡單說明。

負載均衡
gRPC有 關於命名解析grpc/naming和負載均衡grpc/balancer的包。 首先gRPC客戶端會發出服務註冊和域名管理請求,dnsresolver包裝連接對象註冊,並通過wrapper和client端回調更新。client端再調用balancer部分接口實現對連接的管理 負載均衡,用於管理連接狀態和生命週期。並偵聽每一個subconn的狀態變化進行策略反饋,負責發起連接的創建和移除。負載均衡策略支持外部擴展以避免更改gRPC內部的東西,其中gRPCLB就是loadbalancer,用於包含外部的實現,內置的grpc/balancer/roundrobin應該是一個簡單的可供擴展的循環平衡機制,總之爲balancer管理狀態而服務。這樣通過對連接的管理優化client端和server之間的gRPC。

下圖是grpc的一個總體架構,可以有一個簡單認識。

                                                  fig.5 gRPC structure

超時保活

RPC連接時channel作爲數據的載體,共分爲5種狀態:Idle,Connecting,Ready,TransientFailure,Shutdown,可見grpc/connectivity.go。重連機制通過啓動一個Goroutine異步的去建立連接實現的,可以避免服務器因爲連接空閒時間過長關閉連接、服務器重啓等造成的客戶端連接失效問題。也就是說通過gRPC的重連機制可以完美的解決連接池設計原則中的空閒連接的超時與保活問題。

                                                fig.6 grpc/conectivity

grpc/keepalive
這個包分別爲client和server定義了測試傳輸路徑是否work的參數來協調池中的連接數
client端:
當一段時間客戶端沒有請求發送,客戶端就會向server發送ping消息,等待一段時間看傳輸是否受損,來檢測server的狀態
server端:維護最大空閒連接時間,最大空閒連接數等,最大空閒連接時間默認值最大,我們可以調用這個來完成對用戶連接的空閒時間管理

                                             fig.7  grpc/keepalive

gRPC使用HTTP/2作爲應用層的傳輸協議,很多機制與http/2相關,比如利用流的多路複用等。當由於缺少新的或待處理的RPC,channel沒有嘗試創建連接就會變成idle狀態,或者當沒有新的或掛起的(活動的)RPC,則READY或CONNECTING的channel也會切換到IDLE。此時,server 端會給client 端發送一個http GOAWAY 的包,client 收到這個包之後就會主動關閉連接。下次需要發包的時候,就會重新建立連接,以避免試圖斷開連接的服務器上的連接過載。

 

參考:

1. nokia and grpc: https://infocenter.nokia.com/public/7750SR160R4A/index.jsp?topic=%2Fcom.sr.system.mgmt%2Fhtml%2Ftelemetry-intro.html

2. 知乎grpc源碼筆記:https://zhuanlan.zhihu.com/p/104060740

3. grpc官方文檔:https://grpc.io

4. grpc go github:https://github.com/grpc/grpc-go

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章