既然有HTTP協議,為什麼還要有RPC?

来源:https://www.cnblogs.com/88223100/archive/2023/09/13/Since-there-is-an-HTTP-protocol-why-should-there-be-RPC.html
-Advertisement-
Play Games

我想起了我剛工作的時候,第一次接觸RPC協議,當時就很懵,我HTTP協議用得好好的,為什麼還要用RPC協議? 於是就到網上去搜。 不少解釋顯得非常官方,我相信大家在各種平臺上也都看到過,解釋了又好像沒解釋,都在用一個我們不認識的概念去解釋另外一個我們不認識的概念,懂的人不需要看,不懂的人看了還是不懂 ...


我想起了我剛工作的時候,第一次接觸RPC協議,當時就很懵,我HTTP協議用得好好的,為什麼還要用RPC協議?

 

於是就到網上去搜。

 

不少解釋顯得非常官方,我相信大家在各種平臺上也都看到過,解釋了又好像沒解釋,都在用一個我們不認識的概念去解釋另外一個我們不認識的概念,懂的人不需要看,不懂的人看了還是不懂。

 

這種看了,又好像沒看的感覺,雲里霧裡很難受,我懂

 

為了避免大家有強烈的審醜疲勞,今天我們來嘗試重新換個方式講一講。

 

一、從TCP聊起

 

作為一個程式員,假設我們需要在A電腦的進程發一段數據到B電腦的進程,我們一般會在代碼里使用socket進行編程。

 

這時候,我們可選項一般也就TCP和UDP二選一TCP可靠,UDP不可靠。除非是馬總這種神級程式員(早期QQ大量使用UDP),否則,只要稍微對可靠性有些要求,普通人一般無腦選TCP就對了。

 

類似下麵這樣。

 

  •  
fd = socket(AF_INET,SOCK_STREAM,0);

 

其中SOCK_STREAM,是指使用位元組流傳輸數據,說白了就是TCP協議

 

在定義了socket之後,我們就可以愉快地對這個socket進行操作,比如用bind()綁定IP埠,用connect()發起建連。

 

圖片

握手建立連接流程

 

在連接建立之後,我們就可以使用send()發送數據,recv()接收數據。

 

光這樣一個純裸的TCP連接,就可以做到收發數據了,那是不是就夠了?

 

不行,這麼用會有問題。

 

二、使用純裸TCP會有什麼問題

 

八股文常背,TCP是有三個特點,面向連接、可靠、基於位元組流

 

圖片

TCP是什麼

 

這三個特點真的概括得非常精辟,這個八股文我們沒白背。

 

每個特點展開都能聊一篇文章,而今天我們需要關註的是基於位元組流這一點。

 

位元組流可以理解為一個雙向的通道里流淌的數據,這個數據其實就是我們常說的二進位數據,簡單來說就是一大堆 01 串。純裸TCP收發的這些 01 串之間是沒有任何邊界的,你根本不知道到哪個地方纔算一條完整消息。

 

圖片

01二進位位元組流

 

正因為這個沒有任何邊界的特點,所以當我們選擇使用TCP發送"夏洛"和"特煩惱"的時候,接收端收到的就是"夏洛特煩惱",這時候接收端沒法區分你是想要表達"夏洛"+"特煩惱"還是"夏洛特"+"煩惱"。

 

圖片

消息對比

 

這就是所謂的粘包問題,之前也寫過一篇專門的文章聊過這個問題。

 

說這個的目的是為了告訴大家,純裸TCP是不能直接拿來用的,你需要在這個基礎上加入一些自定義的規則,用於區分消息邊界。

 

於是我們會把每條要發送的數據都包裝一下,比如加入消息頭,息頭裡寫清楚一個完整的包長度是多少,根據這個長度可以繼續接收數據,截取出來後它們就是我們真正要傳輸的消息體。

 

圖片

消息邊界長度標誌

 

而這裡頭提到的消息頭,還可以放各種東西,比如消息體是否被壓縮過和消息體格式之類的,只要上下游都約定好了,互相都認就可以了,這就是所謂的協議

 

每個使用TCP的項目都可能會定義一套類似這樣的協議解析標準,他們可能有區別,但原理都類似

 

於是基於TCP,就衍生了非常多的協議,比如HTTP和RPC。

 

三、HTTP和RPC

 

我們回過頭來看網路的分層圖。

 

圖片

四層網路協議

 

TCP是傳輸層的協議,而基於TCP造出來的HTTP和各類RPC協議,它們都只是定義了不同消息格式的應用層協議而已。

 

HTTP協議(Hyper Text Transfer Protocol),又叫做超文本傳輸協議。我們用的比較多,平時上網在瀏覽器上敲個網址就能訪問網頁,這裡用到的就是HTTP協議。

 

圖片

HTTP調用

 

RPC(Remote Procedure Call),又叫做遠程過程調用。它本身並不是一個具體的協議,而是一種調用方式

 

舉個例子,我們平時調用一個本地方法就像下麵這樣。

 

  •  
 res = localFunc(req)

 

如果現在這不是個本地方法,而是個遠端伺服器暴露出來的一個方法remoteFunc,如果我們還能像調用本地方法那樣去調用它,這樣就可以屏蔽掉一些網路細節,用起來更方便,豈不美哉?

 

  •  
 res = remoteFunc(req)

 

圖片

RPC可以像調用本地方法那樣調用遠端方法

 

基於這個思路,大佬們造出了非常多款式的RPC協議,比如比較有名的gRPC,thrift。

 

值得註意的是,雖然大部分RPC協議底層使用TCP,但實際上它們不一定非得使用TCP,改用UDP或者HTTP,其實也可以做到類似的功能。

 

圖片

基於TCP協議的HTTP和RPC協議

 

到這裡,我們回到文章標題的問題。

 

既然有HTTP協議,為什麼還要有RPC?

 

其實,TCP是70年代出來的協議,而HTTP是90年代才開始流行的。而直接使用裸TCP會有問題,可想而知,這中間這麼多年有多少自定義的協議,而這裡面就有80年代出來的RPC。

 

所以我們該問的不是既然有HTTP協議為什麼要有RPC,而是為什麼有RPC還要有HTTP協議。

 

那既然有RPC了,為什麼還要有HTTP呢?

 

現在電腦上裝的各種聯網軟體,比如xx管家,xx衛士,它們都作為客戶端(client)需要跟服務端(server)建立連接收發消息,此時都會用到應用層協議,在這種client/server (c/s)架構下,它們可以使用自家造的RPC協議,因為它只管連自己公司的伺服器就ok了。

 

但有個軟體不同,瀏覽器(browser),不管是chrome還是IE,它們不僅要能訪問自家公司的伺服器(server),還需要訪問其他公司的網站伺服器,因此它們需要有個統一的標準,不然大家沒法交流。於是,HTTP就是那個時代用於統一 browser/server (b/s) 的協議。

 

也就是說在多年以前,HTTP主要用於b/s架構,而RPC更多用於c/s架構。但現在其實已經沒分那麼清了,b/s和c/s在慢慢融合。很多軟體同時支持多端,比如某度雲盤,既要支持網頁版,還要支持手機端和pc端,如果通信協議都用HTTP的話,那伺服器只用同一套就夠了。而RPC就開始退居幕後,一般用於公司內部集群里,各個微服務之間的通訊。

 

那這麼說的話,都用HTTP得了,還用什麼RPC?

 

仿佛又回到了文章開頭的樣子,那這就要從它們之間的區別開始說起。

 

四、HTTP和RPC有什麼區別

 

我們來看看RPC和HTTP區別比較明顯的幾個點。

 

1.服務發現

 

首先要向某個伺服器發起請求,你得先建立連接,而建立連接的前提是,你得知道IP地址和埠。這個找到服務對應的IP埠的過程,其實就是服務發現

 

HTTP中,你知道服務的功能變數名稱,就可以通過DNS服務去解析得到它背後的IP地址,預設80埠。

 

RPC的話,就有些區別,一般會有專門的中間服務去保存服務名和IP信息,比如consul或者etcd,甚至是redis。想要訪問某個服務,就去這些中間服務去獲得IP和埠信息。由於dns也是服務發現的一種,所以也有基於dns去做服務發現的組件,比如CoreDNS。

 

可以看出服務發現這一塊,兩者是有些區別,但不太能分高低。

 

2.底層連接形式

 

以主流的HTTP1.1協議為例,其預設在建立底層TCP連接之後會一直保持這個連接(keep alive),之後的請求和響應都會復用這條連接。

 

RPC協議,也跟HTTP類似,也是通過建立TCP長鏈接進行數據交互,但不同的地方在於,RPC協議一般還會再建個連接池,在請求量大的時候,建立多條連接放在池內,要發數據的時候就從池裡取一條連接出來,用完放回去,下次再復用,可以說非常環保。

 

圖片

connection_pool

 

由於連接池有利於提升網路請求性能,所以不少編程語言的網路庫里都會給HTTP加個連接池,比如go就是這麼乾的。

 

可以看出這一塊兩者也沒太大區別,所以也不是關鍵。

 

3.傳輸的內容

 

基於TCP傳輸的消息,說到底,無非都是消息頭header和消息體body

 

header是用於標記一些特殊信息,其中最重要的是消息體長度。

 

body則是放我們真正需要傳輸的內容,而這些內容只能是二進位01串,畢竟電腦只認識這玩意。所以TCP傳字元串和數字都問題不大,因為字元串可以轉成編碼再變成01串,而數字本身也能直接轉為二進位。但結構體呢,我們得想個辦法將它也轉為二進位01串,這樣的方案現在也有很多現成的,比如json,protobuf

 

這個將結構體轉為二進位數組的過程就叫序列化,反過來將二進位數組複原成結構體的過程叫反序列化

 

圖片

序列化和反序列化

 

對於主流的HTTP1.1,雖然它現在叫超文本協議,支持音頻視頻,但HTTP設計初是用於做網頁文本展示的,所以它傳的內容以字元串為主。header和body都是如此。在body這塊,它使用json來序列化結構體數據。

 

我們可以隨便截個圖直觀看下。

 

圖片

HTTP報文

 

可以看到這裡面的內容非常多的冗餘,顯得非常啰嗦。最明顯的,像header里的那些信息,其實如果我們約定好頭部的第幾位是content-type,就不需要每次都真的把"content-type"這個欄位都傳過來,類似的情況其實在body的json結構里也特別明顯。

 

而RPC,因為它定製化程度更高,可以採用體積更小的protobuf或其他序列化協議去保存結構體數據,同時也不需要像HTTP那樣考慮各種瀏覽器行為,比如302重定向跳轉啥的。因此性能也會更好一些,這也是在公司內部微服務中拋棄HTTP,選擇使用RPC的最主要原因

 

圖片

HTTP原理

 

圖片

RPC原理

 

當然上面說的HTTP,其實特指的是現在主流使用的HTTP1.1,HTTP2在前者的基礎上做了很多改進,所以性能可能比很多RPC協議還要好,甚至連gRPC底層都直接用的HTTP2。

 

那麼問題又來了。

 

為什麼既然有了HTTP2,還要有RPC協議?

 

這個是由於HTTP2是2015年出來的。那時候很多公司內部的RPC協議都已經跑了好些年了,基於歷史原因,一般也沒必要去換了。

 

總結

 

  • 純裸TCP是能收發數據,但它是個無邊界的數據流,上層需要定義消息格式用於定義消息邊界。於是就有了各種協議,HTTP和各類RPC協議就是在TCP之上定義的應用層協議。

     

  • RPC本質上不算是協議,而是一種調用方式,而像gRPC和thrift這樣的具體實現,才是協議,它們是實現了RPC調用的協議。目的是希望程式員能像調用本地方法那樣去調用遠端的服務方法。同時RPC有很多種實現方式,不一定非得基於TCP協議。

     

  • 從發展歷史來說,HTTP主要用於b/s架構,而RPC更多用於c/s架構。但現在其實已經沒分那麼清了,b/s和c/s在慢慢融合。很多軟體同時支持多端,所以對外一般用HTTP協議,而內部集群的微服務之間則採用RPC協議進行通訊。

     

  • RPC其實比HTTP出現得要早,且比目前主流的HTTP1.1性能要更好,所以大部分公司內部都還在使用RPC。

     

  • HTTP2.0在HTTP1.1的基礎上做了優化,性能可能比很多RPC協議都要好,但由於是這幾年才出來的,所以也不太可能取代掉RPC。

 

最後留個問題吧,大家有沒有發現,不管是HTTP還是RPC,它們都有個特點,那就是消息都是客戶端請求,服務端響應。客戶端沒問,服務端肯定就不答,這就有點僵了,但現實中肯定有需要下游主動發送消息給上游的場景,比如打個網頁游戲,站在那啥也不操作,怪也會主動攻擊我,這種情況該怎麼辦呢?

 

>>>>

參考資料

 

  • https://www.zhihu.com/question/41609070

 

作者丨小白

本文來自博客園,作者:古道輕風,轉載請註明原文鏈接:https://www.cnblogs.com/88223100/p/Since-there-is-an-HTTP-protocol-why-should-there-be-RPC.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Apache SeaTunnel是一個非常易於使用的、超高性能的分散式數據集成平臺,支持海量數據的實時同步。每天可穩定高效同步數百億數據,已被近百家企業投入生產使用。 現在的版本不支持通過jtds的方式鏈接sqlserver,我們來自己寫代碼來實現它,並把代碼提交給apache seatunnel。 ...
  • 通過 API 對外提供數據服務是大部分企業中比較常見的數據應用方式,對於 API 平臺管理者、開發者和調用者來說,API 的調用性能、安全性和穩定性是在平臺選型時最需要考慮的三個因素。 袋鼠雲API開發及管理平臺【數棧-數據服務 DataAPI】通過多種手段標準化管控服務,可完成從 API 創建、發 ...
  • 業務挑戰與痛點 隨著互聯網技術的發展、雲計算技術的成熟、人工智慧技術的興起和數字化經濟的崛起,數據已成為企業的核心資產。在金融行業中,數字化已成為了支撐各類業務場景的核心力量,包括個人理財、企業融資、股票交易、保險理賠、貸款服務、支付結算、投資咨詢、資產管理等等。然而,在基於大數據分析與處理技術的業 ...
  • 起因 在GreatSQL社區上有一位用戶提出了“手工構建MGR碰到的次節點一直處於recovering狀態”,經過排查後,發現了是因為新密碼驗證插件caching_sha2_password導致的從節點一直無法連接主節點,帖子地址:(https://greatsql.cn/thread-420-2- ...
  • Android的源碼非常的龐大,編譯Android系統往往會占用我們很長的時間,我們需要瞭解下Android的編譯規則,以期能提高我們的開發效率。。。 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 為了更好的瞭解原神角色,我模仿官網做了一個角色切換效果,在做的過程當中也總結了一些技術點。 為了讓大家更好的體驗,我相容了 PC 端和移動端,建議在 PC 端查看效果更佳。接下來就為大家簡單的分享一下! 話不多說,原神啟動!! 效果 ...
  • 工作中經常會遇到監聽數組發生變化時執行相應的回調觸發邏輯,客戶應用場景中需要實現對象變數的動態監聽,當變數發生變化時觸發回調函數,實現事件發送等應用場景。 通常由以下兩種方式實現需求 一.通過改變對象原型prototype方法實現回調監聽 //創建一個數組原型對象 var arrayProtoTyp ...
  • nvm、node、vue安裝、創建vue項目 nvm作用:可以管理多個版本的node,切換node版本,下載node。 前情提要 參 考:https://zhuanlan.zhihu.com/p/519270555 下載地址:https://github.com/coreybutler/nvm-wi ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...