RPC與REST

RPC與REST

        • 訪問遠程服務
          • 1遠程服務調用(Remote Procedure Call,RPC):RPC 解決什么問題?如何解決的?為什么要那樣解決?
            • 1.1 先解決兩個進程間如何交換數據的問題,也就是進程間通信(Inter-Process Communication,IPC)。可以考慮的辦法有以下幾種:
            • 1.2 通信的成本
            • 1.3 三個基本問題
            • 1.4 統一的 RPC 與 分裂的 RPC
          • 2 REST 設計風格
            • 2.1 理解 REST
            • 2.2 RESTful 的系統

訪問遠程服務

遠程服務將計算機的工作范圍從單機擴展到網絡,從本地延伸至遠程,是構建分布式系統的首要基礎。

而遠程服務又不僅僅是為了分布式系統服務的,在網絡時代,瀏覽器、移動設備、桌面應用和服務端的程序,普遍都有與其他設備交互的需求,所以今天很難找到沒有開發過遠程服務的人,但是沒有正確理解遠程服務的coder比比皆是。

1遠程服務調用(Remote Procedure Call,RPC):RPC 解決什么問題?如何解決的?為什么要那樣解決?

進程間通信:盡管今天的大多數RPC 已經不再追求這個目標了,但無可否認,在最初的時候,這是先要解決的:讓調用遠程方法和本地方法一樣。

1.1 先解決兩個進程間如何交換數據的問題,也就是進程間通信(Inter-Process Communication,IPC)。可以考慮的辦法有以下幾種:
  1. 管道或具名管道:管道類似于兩個進程間的橋梁,可通過管道在進程間傳遞 少量的字符流或字節流。普通管道只用于有親緣關系的進程(由一個進程啟動的另外一個進程)間通信。具名管道拜托了普通管道沒有名字的限制,除具有普通管道的所有功能外,它還允許無親緣關系進程間的通信。管道典型的應用就是命令行中的 | 操作符,如:ps -ef | grep java ps 與 grep 都有獨立的進程,以上命令就是將ps 的標準輸出鏈接到grep 的標準輸入上。
  2. 信號(signal):用于通知目標進程有某事發生,除了用于進程間通信外,進程還可以發送信號給進程自身。信號的典型命令就是 kill 命令:kill -9 pid
  3. 信號量(Semaphore):信號量用于兩個進程間同步協作手段,它相當于操作系統提供的一個特殊變量,程序可以在上面進行 wait() notify() 操作。
  4. 消息隊列:以上三種方式只適合傳遞少量信息,消息隊列用于進程間數據量較多的通信。進程可以向隊列添加消息,被賦予讀權限的進程可以消費消息,MQ 克服了信號承載量小,管道只能用于無格式字節流以及緩沖區大小受限的缺點,但實時性相對受限。
  5. 共享內存(Shared Memory) :允許多個進程訪問同一塊公共的內存空間,這是效率最高的進程間通信方式。當一塊進程被多進程共享時,各個進程往往會與其他通信機制,如信號量結合使用。
  6. 套接字接口(Socket):消息隊列和共享內存只適合于單機多進程間的通信,套接字接口是更為普適的進程間通信機制,可用于不同機器之間的進程通信。套接字(socket)當僅限于本機進程間通信時,套接字接口是優化過的,不會經過網絡協議棧,不需要打包拆包、計算校驗和等,只是簡單的將應用層數據從一個進程拷貝到另一個進程。這種進程間通信叫 IPC Socket。
1.2 通信的成本

IPC Socket 不僅適用于本地相同機器間不同進程間的通信,由于 Socket 網絡棧的統一接口,它也理所應當的能支持基于網絡的跨機器進程間通信。這么做有一個看起來無比誘人的好處,由于 Socket 是各個操作系統都有提供的標準接口,完全有可能把遠程方法調用的通信細節隱藏在操作系統底層,從應用層面商看來可以做到遠程調用與本地的進程間通信在編碼上完全一致。事實上,在原始分布式時代的確是這么用的,但這種透明的調用形式卻反問濫用以至于顯著降低了分布式系統的性能。
所以,對 RPC 提出一系列的疑問:

  1. 兩個進程間通信,誰作為客戶端,誰作為服務端?
  2. 怎樣進行異常處理,如何讓調用者獲知?
  3. 服務端出現多線程競爭后改怎么辦?
  4. 如何提高網絡利用的效率?比如連接是否可以被多個請求復用以減少開銷,是否支持多播?
  5. 參數、返回值如何表示?應該有怎樣的字節序?
  6. 如何保證網絡的可靠性?
  7. 發送的請求服務端收不到回復怎么辦?

這里的中心觀點是:本地調用與遠程調用當做一樣處理,這是犯了方向性的錯誤。
Sun 公司的一眾大佬們總結了通過網絡記性分布式運算的八宗罪:

  1. 網路是可靠的,安全的,同質化的;(這是三點)
  2. 延遲是不存在的;
  3. 帶寬是無限的;
  4. 拓撲結構是一成不變的;
  5. 總會有一個管理員;
  6. 不必考慮傳輸成本。

以上八大問題潛臺詞就是說如果遠程服務調用要弄透明化的話,就必須為這些罪過埋單(就是RPC不能透明化)。這算是給 RPC 是否能等同于 IPC 正式定下了一個具有公信力的結論。至此,RPC 應該是一種高層次的或者說語言層次的特征,而不是像 IPC 那樣,是低層次的貨系統層次的特征成為工業界、學術界的主流觀點

RPC 的定義:遠程服務調用是指位于互不重合的內存地址空間中的兩個程序,在語言層面上,以同步的方式使用有限帶寬的信道來傳輸程序控制信息。

1.3 三個基本問題

RPC 協議無外乎變著花樣使用各種手段來解決以下三個基本問題:

  • 如何表示數據:這里的數據包含了傳遞給方法的參數,以及方法執行后的返回值。不同進程間數據讀取問題。且 RPC 完全可能綿連交互雙方各自使用不同程序語言的情況:即使是用了相同語言的 RPC 協議,在不同硬件指令集、不同OS下,同樣的數據類型也完全可能有不一樣的表現細節,如數據寬度、字節差異等。有效的做法是:將交互雙方所涉及的數據轉換為某種事先約定好的中立數據流格式來進行傳輸,將數據流轉換回不同語言中對應的數據類型來進行使用,就是序列化與反序列化。每種 RPC 協議都要有對應的序列化協議,如 gRPC Protocol Buffers,其他眾多輕量級 RPC 的 JSON Serialization。
  • 如何傳輸數據:指如何通過網路,在兩個服務的 Endpoint 間相互操作、交換數據。這里的“交換數據”通常指的是應用層協議,實際傳輸一般是基于標準的 TCP、UDP 等標準的傳輸層協議來完成的。兩個服務交互不只是扔個序列化數據就行,還需有異常、超時、安全、認證、授權、事務等,這些都可能是雙方需交換的。這類數據叫:Wire Protocol。常見的有:Java RMI 的 JRMP,Web Service 的 SOAP,如果要求足夠簡單,雙方都是 HTTP Endpoint,就可直接使用 HTTP 協議(如 JSON-RPC)。
  • 如何確定方法:這在本地方法調用中不是太大問題,編譯器會根據語言規范,將調用的方法簽名轉換為進程空間中子過程入口位置的指針。不過一旦要考慮不同語言事情又麻煩起來,每門語言的方法前面可能不同,所以“如何表示同一個方法”,“找到對應的方法”還是得弄個跨語言的統一標準。這個標準非常簡單,如直接給程序的每個方法都規定一個唯一的、在任何機器上都絕不重復的編號,直接找對應方法。這是當初DCE 的解決方案,就是 UUID,雖然此后DCE 還是弄了一套語言無關的接口描述語言(Interface Description Language,IDL),但 UUID 卻廣為流傳。用于表示方法的協議:Web Service 的 WSDL,JSON-RPC 的JSON-WSP。
1.4 統一的 RPC 與 分裂的 RPC

剛開始的時候,大家總是嘗試 RPC 可以解決所有分布式問題,如剛開始的時候既要支持面向對象,又要支持多種語言,功能還齊全。但是沒有一家成功的,簡單、普適、高性能這三點,似乎真的難以同時滿足。所以現在的 RPC 仍處于百家爭鳴的時代,大家都不再去追求大而全的“完美”,而是有自己的針對性作為主要的發展方向。如:

  1. 面向對象發展的 RMI等;
  2. 朝著性能發展的,如 gRPC 和 Thrift,決定 RPC 性能的主要兩個因素:序列化效率和信息密度。序列化效率指輸出結果容量小,速度快,效率自然高;信息密度則取決于協議中有效負載(Payload)所占總傳輸數據的比例大小,使用傳輸協議的層次越高,信息密度越低,SOAP 使用XML拙劣的性能表現就是前車之鑒。gRPC 和 Thrift 都有自己優秀的專有序列化器,而傳輸協議方面,gRPC 是基于 HTTP/2 的,支持多路復用和 Header 壓縮,Thrift 則直接基于傳輸層的 TCP 協議來實現,省去了額外應用層協議的開銷。
  3. 朝著簡化發展:代表為 JSON-RPC,要說功能最強、速度最快的 RPC 可能會很有爭議,但選功能弱的、速度慢的,JSON-RPC 肯定會在候選人之一。犧牲了功能和效率,換來的是協議的簡單輕便,接口與格式都更為通用,尤其適合用于 Web 瀏覽器這類一般不會有額外協議支持、額外客戶端支持的應用場合。

到了最近幾年,RPC 框架有明顯的朝著更高層次(不僅負責調用遠程服務,還要管理遠程服務)與插件化方向發展的趨勢,不再追求獨立地解決 RPC 的全部三個問題(表示數據、傳遞數據、表示方法),而是將一部分功能設計成擴展點,讓用戶自己去選擇。框架聚焦于提供核心的、更高層次的能力,如提供負載均衡、服務注冊、可觀察性等方面的支持。這一類框架的代表有 Facebook 的 Thrift 和阿里的 Dubbo。尤其是斷更多年后重啟的 Dubbo 表現得更為明顯,它默認有自己的傳輸協議(Dubbo協議),同時也支持其他協議;默認采用 Hessian2 作為序列化器,如果你有 JSON 需求,可以替換為 Fastjson,如你對性能有更高的追求,可以替換為 Kryo、Protocol Buffers 等效率更好的序列化器,如果你不想依賴其他組件庫,直接使用 JDK 自帶的序列化器也是可以的。

開發一個分布式系統,是不是一定要用 RPC 呢?

2 REST 設計風格

很多人會拿 REST 與 RPC 互相比較,其實,REST 無論是在思想上、概念上,還是適用范圍上,與 RPC 都不盡相同,充其量只能算有些相似,但本質上并不是同一類型的東西。

2.1 理解 REST

個人會有好惡偏愛,但計算機科學是務實的,有了RPC還會提出REST,有了面向過程編程還能產生面向資源編程,后者總會有些前者沒有的閃光點,我們先理解 REST,在談論評價它。
比較容易理解 REST 思想的途徑是先理解什么是 HTTP,再配合一些實際例子來進行類比,你會發現REST(Representational State Transfer)實際是 HTT(Hypertext Transfer)的進一步抽象,兩者就如同接口與實現類的關系一般。

Hypertext 超文本一詞已被普遍接受,它指的是能夠進行分支判斷和差異響應的文本,相應地,超媒體指的是能夠進行分支判斷和差異響應的圖形、電影和聲音(也包括文本)的復合體。就是指文字可以點擊、可以出發腳本等。

下面從“超文本”或“超媒體”的含義來理解 REST 中的相關概念:

  • 資源(Resource)比如你在閱讀的一篇文章,其內容本身就是資源;

  • 表征(Representation)當你通過電腦瀏覽閱讀此文章時,瀏覽器向服務端發出請求“我需要這個資源的HTML 格式”,服務端向瀏覽器返回的這個 HTML 就是表征,或者是文本的 PDF、Markdown等都是,即表現形式。

  • 狀態(State)當你讀完了這篇文章,想看后面是什么內容時,你想服務器發送“下一篇文章”的請求,但服務端不知道下一篇是哪一篇,就得根據你現在的上下文信息來判斷,以來的就是狀態;

  • 轉移(Transfer)無論狀態是由服務端還是客戶端來提供,“取下一篇文章”這個行為必然只能由服務端來提供,服務端通過某種形式,把當前文章轉變為下一篇,這就叫“表征狀態轉移”。

  • 統一接口(Uniform Interface)前面提到的下一篇的點擊跳轉,這是一種讓表征狀態發生轉移的方式,但是 URI 的含義是統一資源標識符,是一個名詞,如何表達出“轉移”的含義的呢?答案是 HTTP 協議中已經提前約定好了一套“統一接口”,它包括:GET、HEAD POST PUT DELETE TRACE OPTIONS七種基本操作,任何一個支持 HTTP協議的服務器都會遵守這套規定,對特定的 URI 采取這些操作,服務器就會觸發相應的表征狀態轉移的動作。

  • 超文本驅動(Hypertext Driven)任何網站的導航(狀態轉移)行為都不可能是預置于瀏覽器代碼之中,而是由服務器發出的請求響應信息(超文本)來驅動的。

  • 自描述信息 消息的類型以及應如何處理這條消息。如 Content-Type:application/json;charset=utf-8

2.2 RESTful 的系統

理解了上面的概念,我們就可以開始討論面向資源的呢編程思想與幾個具體的軟件架構設計原則了。一套完整的、完全滿足 REST 風格的系統應滿足以下六大原則:

  1. 服務端與客戶端分離(Client-Server)將用戶界面所關注的邏輯和數據存儲所關注的邏輯分離開來,有助于提高用戶界面的跨平臺的可移植性。
  2. 無狀態(Stateless)無狀態是 REST 的一條核心原則,部分開發者在做接口規劃時,覺得 REST 風格的服務怎么設計都感覺別怒,很有可能的一種原因是在服務端持有著比較重的狀態。應由客戶端承擔狀態維護職責,但目前大多數系統都達不到這個要求。
  3. 可緩存(Cacheability)無狀態服務雖然提升了系統的可見性、可靠性和可伸縮性,但降低了系統的網絡性。“降低網絡性”是指某個功能如果使用有狀態的設計只需一次(或少量)請求即可完成,而無狀態的得多次。為了緩解這個矛盾,REST 希望軟件系統能入萬維網一樣,允許客戶端和中間的通訊傳遞者(如代理)將部分服務端的應答緩存起來。
  4. 分層系統(Layered System)這里的分層并不是表示層、服務層、持久層這種,而是客戶端一般不用知道是否直接連接到了最終的服務器,或中間服務器。中間服務器可以通過負載均衡和共享緩存的機制提高系統的可擴展性,這樣也便于緩存、伸縮和安全策略的部署。該原則的典型應用是內容分發網絡。如我們瀏覽某個網站,并不是直接訪問源服務器,而是訪問了某個 CDN 服務器。
  5. 統一接口(Uniform Interface)這是 REST 的另一條核心原則,REST 希望開發者面向資源編程,希望軟件系統設計的重點放在抽象系統該有哪些資源上,而不是抽象系統該有哪些行為上。這條原則可以類比計算機中對文件管理的操作來理解,管理文件的操作是可數的,而且對所有文件都是固定的,統一的。如果面向資源來設計系統,同樣會有類似的操作特征,所有這些操作都借用了HTTP協議中固有的操作命令來完成。因為面向資源編程的抽象程度更高。想要在架構設計中合理恰當的利用統一接口,系統應能做到每次請求中都包含資源的ID,所有操作均通過資源ID 來進行;建議每個資源都是自描述的消息;建議通過超文本來驅動應用狀態的轉移
  6. 按需代碼(Code-On-Demand)可選原則。

本節開篇提出的 REST 與 RPC 在思想上的差異?
REST 的基本思想是面向資源來抽象問題,它與此前流行的面向過程的編程在抽象主體上有本質區別。在 REST 提出以前,人們設計分布式系統的唯一方案就只有 RPC,開發者是圍繞著“遠程方法”去設計兩個系統交互的,這樣做的壞處不僅是“如何在不同系統間表示一個方法”、“如何獲得接口能夠提供的方法清單”都成了需要專門協議去解決的問題,更在于服務的每個方法都是獨立的,服務者必須熟悉每個方法才能使用,而REST抽象為了幾類

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/42061.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/42061.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/42061.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

最新扣子(Coze)實戰案例:使用擴圖功能,讓你的圖任意變換,完全免費教程

🧙?♂? 大家好,我是斜杠君,手把手教你搭建扣子AI應用。 📜 本教程是《AI應用開發系列教程之扣子(Coze)實戰教程》,完全免費學習。 👀 微信關注公從號:斜杠君,可獲取完整版教程。&a…

如何快速搭建python項目的虛擬環境

itopen組織1、提供OpenHarmony優雅實用的小工具2、手把手適配riscv qemu linux的三方庫移植3、未來計劃riscv qemu ohos的三方庫移植 小程序開發4、一切擁抱開源,擁抱國產化 你在開發python工具的時候還一直使用系統默認的環境嗎?是否有遇到有時候…

2024年【北京市安全員-B證】報名考試及北京市安全員-B證最新解析

題庫來源:安全生產模擬考試一點通公眾號小程序 2024年北京市安全員-B證報名考試為正在備考北京市安全員-B證操作證的學員準備的理論考試專題,每個月更新的北京市安全員-B證最新解析祝您順利通過北京市安全員-B證考試。 1、【多選題】《中華人民共和國安…

android輪播圖入門2——觸摸停止與指示器

前言 這次要在上一篇輪播圖的基礎上做改造,增加兩個功能: 用戶觸摸到輪播圖時,停止輪播在輪播圖上展示一個小指示器,指示當前輪播組件的位置 觸摸停播 觸摸停播的設計思路是:監聽實現輪播圖的觸摸事件,…

手把手教你從零開始構建 AI 視頻生成模型

在 GitHub 上發現一篇教程,作者詳細介紹了如何使用 Python 語言,從零開始構建一個文本到視頻生成模型。 涵蓋了從理解理論概念到架構編碼,最終實現輸入文本提示即可生成視頻的全過程。 相關鏈接 GitHub:github.com/FareedKhan-…

python-redis-lock是如何實現鎖自動續期的

python-redis-lock簡介 python-redis-lock是一個python的第三方庫,基于Redis,封裝了分布式鎖的邏輯,提供了更高級的API來簡化鎖的獲取、保持和釋放過程。包括自動續期、鎖超時、重入鎖等功能。 相比于直接使用redis的setnx,避免了…

倒退型自閉癥與輕度自閉癥有什么區別?

作為星貝育園自閉癥兒童康復中心的一名專業教師,我深知家長們在面對自閉癥譜系障礙(ASD)時的種種疑問與挑戰,尤其是關于倒退型自閉癥與輕度自閉癥之間的區別。今天,我將從專業視角出發,深入淺出地解析這兩種…

精通Vim編輯器:Linux系統下的強大文本編輯工具

精通Vim編輯器:Linux系統下的強大文本編輯工具 引言 在Linux世界中,Vim是一個功能強大、高度可定制的文本編輯器,它繼承自經典的vi編輯器并提供了一系列增強功能。無論是系統管理員、開發人員還是普通用戶,掌握Vim的使用都能大幅…

游戲AI的創造思路-技術基礎-強化學習(2)

上一篇中引出了深度強化學習這個大坑,本篇淺淺填一下~~~~ 目錄 6. 深度強化學習概述 6.1. 基本概念 6.2. 發展歷史 6.3. 基本公式 6.4. Python實現 6.5. 運行原理 6.5.1. 核心要素 6.5.2. 運行原理 6.5.3. 典型算法 6.5.4. Python實現代碼 6.6. 優缺點 …

Segmentation fault (core dumped)

錯誤簡介 出現 “Segmentation fault (core dumped)” 錯誤通常意味著程序訪問了未分配的內存或者越界訪問了已分配內存之外的區域。 段錯誤通常發生在以下情況: 空指針解引用:嘗試對空指針進行操作。內存越界:訪問了超出分配內存邊界的區…

大廠面試官贊不絕口的后端技術亮點【后端項目亮點合集(2)】

本文將持續更新~~ hello hello~ ,這里是絕命Coding——老白~💖💖 ,歡迎大家點贊🥳🥳關注💥💥收藏🌹🌹🌹 💥個人主頁:絕命C…

提高論文發表機會:Nature Communications 最新研究教你如何巧妙回復審稿意見

我是娜姐 迪娜學姐 ,一個SCI醫學期刊編輯,探索用AI工具提效論文寫作和發表。 對于科研搬磚人來說,在論文投稿過程中,如何有效回復審稿意見才能得到審稿人的認可,一直是一個讓人困惑又帶點玄學的問題。 但是&#xff0c…

vue3 按鈕復制粘貼功能

1.html <div click"copy(item.envelopePassword)" > 復制口令 </div> 2.utils 創建copy.js export const copy (val: string): void > {let { isSuccessRef } useCopyToClipboard(val) as anyif (isSuccessRef) {// 輕提示showNotify("復制…

【強化學習的數學原理】課程筆記--3(蒙特卡洛方法)

目錄 蒙特卡洛方法MC Basic算法sparse reward MC Greedy 算法樣本使用效率MC ? \epsilon ?-Greedy 算法一些例子 蒙特卡洛方法 第二節 推導貝爾曼最優公式中的&#xff1a; q π k ( s , a ) ∑ r P ( r ∣ s , a ) r γ ∑ s ′ P ( s ′ ∣ s , a ) v π k ( s ′ ) q…

vue3 ~ pinia學習

先看兩個圖 一個vuex 一個pinia 根據圖看出來 pinia更簡單了 那么具體怎么操作呢 我們來看下~ 第一步 下載 yarn add pinia # 或者使用 npm npm install pinia 第二步 注冊 創建一個 pinia 實例 (根 store) 并將其傳遞給應用&#xff1a; import { createApp } from v…

代碼隨想錄算法訓練Day57|LeetCode200-島嶼數量、LeetCode695-島嶼的最大面積

島嶼數量 題目描述 力扣200-島嶼數量 給你一個由 1&#xff08;陸地&#xff09;和 0&#xff08;水&#xff09;組成的的二維網格&#xff0c;請你計算網格中島嶼的數量。 島嶼總是被水包圍&#xff0c;并且每座島嶼只能由水平方向和/或豎直方向上相鄰的陸地連接形成。 此…

前端vue后端java使用easyexcel框架下載表格xls數據工具類

一 使用alibaba開源的 easyexcel框架&#xff0c;后臺只需一個工具類即可實現下載 后端下載實現 依賴 pom.xml <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependen…

MATLAB-分類CPO-RF-Adaboost冠豪豬優化器(CPO)優化RF隨機森林結合Adaboost分類預測(二分類及多分類)

MATLAB-分類CPO-RF-Adaboost冠豪豬優化器&#xff08;CPO&#xff09;優化RF隨機森林結合Adaboost分類預測&#xff08;二分類及多分類&#xff09; 分類CPO-RF-Adaboost冠豪豬優化器&#xff08;CPO&#xff09;優化RF隨機森林結合Adaboost分類預測&#xff08;二分類及多分類…

docker 設置代理,通過代理服務器拉取鏡像

docker 拉取目標鏡像需要通過代理服務器進行時&#xff0c;可以通過為 docker 配置全局代理來實現。 注&#xff1a;Linux 上通過臨時命令 export HTTP_PROXY 設置的代理&#xff0c;對 curl 這些有用&#xff0c;但是對 docker pull 不起作用。 示例 假設您的代理服務器地址是…

Nginx目錄文件作用

查看文件 [rootlocalhost nginx]# pwd /opt/nginx [rootlocalhost nginx]# ll total 4 drwx------ 2 nobody root 6 Jun 6 09:11 client_body_temp drwxr-xr-x 3 root root 4096 Feb 28 14:30 conf drwx------ 2 nobody root 6 Feb 28 14:29 fastcgi_temp drwxr-xr-x…