1. 程式人生 > >深入理解RPC——你看或沒看見 它都在那裡

深入理解RPC——你看或沒看見 它都在那裡

隨著企業 IT 服務的不斷髮展,單臺伺服器逐漸無法承受使用者日益增長的請求壓力時,就需要多臺伺服器聯合起來構成「服務叢集」共同對外提供服務。同時業務服務會隨著產品需求的增多越來越腫,架構上必須進行服務拆分,一個完整的大型服務會被打散成很多很多獨立的小服務,每個小服務會由獨立的程序去管理來對外提供服務,這就是「微服務」。

當用戶的請求到來時,我們需要將使用者的請求分散到多個服務去各自處理,然後又需要將這些子服務的結果彙總起來呈現給使用者。那麼服務之間該使用何種方式進行互動就是需要解決的核心問題。RPC 就是為解決服務之間資訊互動而發明和存在的。

什麼是 RPC ?

RPC (Remote Procedure Call)即遠端過程呼叫,是分散式系統常見的一種通訊方法,已經有 40 多年曆史。當兩個物理分離的子系統需要建立邏輯上的關聯時,RPC 是牽線搭橋的常見技術手段之一。除 RPC 之外,常見的多系統資料互動方案還有分散式訊息佇列、HTTP 請求呼叫、資料庫和分散式快取等。

其中 RPC 和 HTTP 呼叫是沒有經過中介軟體的,它們是端到端系統的直接資料互動。HTTP 呼叫其實也可以看成是一種特殊的 RPC,只不過傳統意義上的 RPC 是指長連線資料互動,而 HTTP 一般是指即用即走的短連結。

RPC 在我們熟知的各種中介軟體中都有它的身影。Nginx/Redis/MySQL/Dubbo/Hadoop/Spark/Tensorflow 等重量級開源產品都是在 RPC 技術的基礎上構建出來的,我們這裡說的 RPC 指的是廣義的 RPC,也就是分散式系統的通訊技術。RPC 在技術中的地位好比我們身邊的空氣,它無處不在,但是又有很多人根本不知道它的存在。

Nginx 與 RPC

Ngnix 是網際網路企業使用最為廣泛的代理伺服器。它可以為後端分散式服務提供負載均衡的功能,它可以將後端多個服務地址聚合為單個地址來對外提供服務。如圖,Django 是 Python 技術棧最流行的 Web 框架。

Nginx 和後端服務之間的互動在本質上也可以理解為 RPC 資料互動。也許你會爭辯說 Nginx 和後端服務之間使用的是 HTTP 協議,走的是短連線,嚴格上不能算是 RPC 呼叫。

你說的沒錯,不過 Nginx 和後端服務之間還可以走其它的協議,比如 uwsgi 協議、fastcgi 協議等,這兩個協議都是採用了比 HTTP 協議更加節省流量的二進位制協議。如上圖所示,uWSGI 是著名的 Python 容器,使用它可以啟動 uwsgi 協議的伺服器對外提供服務。

uwsgi 通訊協議在 Python 語言體系裡使用非常普遍,如果一個企業內部使用 Python 語言棧搭建 Web 服務,那麼他們在生產環境部署 Python 應用的時候不是在使用 HTTP 協議就是在使用 uwsgi 協議來和 Nginx 之間建立通訊。

Fastcgi 協議在 PHP 語言體系裡非常常見,Nginx 和 PHP-fpm 程序之間一般較常使用 Fastcgi 協議進行通訊。

Hadoop 與 RPC

在大資料技術領域,RPC 也佔據了非常重要的地位。大資料領域廣泛應用了非常多的分散式技術,分散式意味著節點的物理隔離,隔離意味著需要通訊,通訊意味著 RPC 的存在。大資料需要通訊的量比業務系統更加龐大,所以在資料通訊優化上做的更深。

比如最常見的 Hadoop 檔案系統 hdfs,一般包括一個 NameNode 和多個 DataNode,NameNode 和 DataNode 之間就是通過一種稱為 Hadoop RPC 的二進位制協議進行通訊。

TensorFlow 與 RPC

在人工智慧領域,RPC 也很重要,著名的 TensorFlow 框架如果需要處理上億的資料,就需要依靠分散式計算力,需要叢集化,當多個分散式節點需要集體智慧時,就必須引入 RPC 技術進行通訊。Tensorflow Cluster 的 RPC 通訊框架使用了 Google 內部自研的 gRPC 框架。

HTTP 呼叫其實也是一種特殊的 RPC

HTTP1.0 協議時,HTTP 呼叫還只能是短連結呼叫,一個請求來回之後連線就會關閉。HTTP1.1 在 HTTP1.0 協議的基礎上進行了改進,引入了 KeepAlive 特性可以保持 HTTP 連線長時間不斷開,以便在同一個連線之上進行多次連續的請求,進一步拉近了 HTTP 和 RPC 之間的距離。

當 HTTP 協議進化到 2.0 之後,Google 開源了一個建立在 HTTP2.0 協議之上的通訊框架直接取名為 gRPC,也就是 Google RPC,這時 HTTP 和 RPC 之間已經沒有非常明顯的界限了。所以在後文我們不再明確強調 RPC 和 HTTP 請求呼叫之間的細微區別了,直接統一稱之為 RPC。

HTTP VS RPC (普通話 VS 方言)

HTTP 與 RPC 的關係就好比普通話與方言的關係。要進行跨企業服務呼叫時,往往都是通過 HTTP API,也就是普通話,雖然效率不高,但是通用,沒有太多溝通的學習成本。但是在企業內部還是 RPC 更加高效,同一個企業公用一套方言進行高效率的交流,要比通用的 HTTP 協議來交流更加節省資源。整個中國有非常多的方言,正如有很多的企業內部服務各有自己的一套互動協議一樣。雖然國家一直在提倡使用普通話交流,但是這麼多年過去了,你回一趟家鄉探個親什麼的就會發現身邊的人還是流行說方言。

如果再深入一點說,普通話本質上也是一種方言,只不過它是官方的方言,使用最為廣泛的方言,相比而言其它方言都是小語種,小語種之中也會有幾個使用比較廣泛比較特色的方言佔比也會比較大。這就好比開源 RPC 協議中 Protobuf 和 Thrift 一樣,它們兩應該是 RPC 協議中使用最為廣泛的兩個。

換個角度看世界

如果兩個子系統沒有在網路上進行分離,而是執行在同一個作業系統例項之上的兩個程序時,它們之間的通訊手段還可以更加豐富。除了以上提到的幾種分散式解決方案之外,還有共享記憶體、訊號量、檔案系統、核心訊息佇列、管道等,本質上都是通過作業系統核心機制來進行資料和訊息的互動而無須經過網路協議棧。

但在現代企業服務中,這種單機應用已經非常少見了,因為單機應用意味著單點故障 —— “一人摔跤全家跌倒”。業務子系統往往都需要經物理網路棧進行隔離,因此分散式解決方案在要求高可用無間斷服務的企業環境裡便大有作為,這也讓 RPC 迎來自己大放異彩的時代。

前文提到的分散式子系統互動方案,除了 RPC 技術之外還有資料庫、訊息佇列和快取。但其實這三者本質上是 RPC 技術的一個應用組合。我們可以將資料庫服務理解為下面這張圖:

可以看出,子系統和資料庫之間的互動也是通過 RPC 進行的,只不過這裡是三個子系統之間複雜的組合訊息互動罷了。如果再深入進去,你會發現,這裡的資料庫不是那種單機資料庫,而是具備主從複製功能的資料庫,比如 MySQL。在網際網路企業裡一般都會使用這種主從讀寫分離的資料庫。一個業務子系統將資料寫往主庫,主庫再將資料同步到從庫,然後另一個業務子系統又從從庫裡將資料取出來。這時又可以進一步將它們看成是四個子系統之間進行的更加複雜的 RPC 資料互動。

小結

現在,讀者應該可以深刻理解 RPC 在網際網路企業技術中的重要地位。從技術複雜性角度,也應該可以明白為什麼說對 RPC 技術的理解水平是評判一個程式設計師是不是高階程式設計師的重要標準之一。

在下一節,我們將對 RPC 的互動原理進行深入的學習,先把地基打牢,再開始實戰開發。

思考題

請讀者思考一下,在平時的後端開發中,還有哪些地方用到了「類 RPC」技術?

在此我向大家推薦一個Java高階群 :725633148裡面會分享一些資深架構師錄製的視訊錄影:(有Spring,MyBatis,Netty原始碼分析,高併發、高效能、分散式、微服務架構的原理,JVM效能優化、分散式架構)等這些成為架構師必備的知識體系 進群馬上免費領取,目前受益良多!