天天看點

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發出。

Golang基礎第五篇——golang的gRPC

                           fig.1 grpc protocol stack

gPRC和上層Protobuf

 服務接口和傳遞的消息均以protobuf的IDL語言統一描述:分别以service和message對象表示。protoc支援插件,grpc就是通過grpc插件來實作用protoc生成client和server的代碼。client的代碼被稱為stub。server端的主要代碼實際上是一個接口。使用者需要自己提供一個類,實作該接口,啟動server時把這個類注冊成這個服務的實作類。即protobuf負責資料的定義,編譯生成grpc可識别的IDL。

Golang基礎第五篇——golang的gRPC

                            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的加密和認證機制也可以直接利用之。

Golang基礎第五篇——golang的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的一個總體架構,可以有一個簡單認識。

Golang基礎第五篇——golang的gRPC

                                                  fig.5 gRPC structure

逾時保活

RPC連接配接時channel作為資料的載體,共分為5種狀态:Idle,Connecting,Ready,TransientFailure,Shutdown,可見grpc/connectivity.go。重連機制通過啟動一個Goroutine異步的去建立連接配接實作的,可以避免伺服器因為連接配接空閑時間過長關閉連接配接、伺服器重新開機等造成的用戶端連接配接失效問題。也就是說通過gRPC的重連機制可以完美的解決連接配接池設計原則中的空閑連接配接的逾時與保活問題。

Golang基礎第五篇——golang的gRPC

                                                fig.6 grpc/conectivity

grpc/keepalive

這個包分别為client和server定義了測試傳輸路徑是否work的參數來協調池中的連接配接數

client端:

當一段時間用戶端沒有請求發送,用戶端就會向server發送ping消息,等待一段時間看傳輸是否受損,來檢測server的狀态

server端:維護最大空閑連接配接時間,最大空閑連接配接數等,最大空閑連接配接時間預設值最大,我們可以調用這個來完成對使用者連接配接的空閑時間管理

Golang基礎第五篇——golang的gRPC

                                             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