面試問微服務設計選RESTful還是RPC,看完這篇徹底搞懂!

2020-08-29 程式設計師檸檬橙

文章每周持續更新,原創不易,你的「點讚」「關注」是對我最大的肯定。



本文是後端微服務架構系列的第二篇文章。在微服務架構中服務之間的通信方式常見的有兩種:RPC 和 REST,關於微服務和 RPC 的更多細節,可以參考我上一篇文章

這篇文章主要介紹什麼是 REST 風格設計以及 RESTful 接口。閱讀完本文你將收穫以下知識點:

  • 什麼是 REST 和 RESTful
  • REST 接口設計規範是什麼
  • REST 為什麼要設計成無狀態
  • 接口無狀態真的是沒有狀態嗎
  • RPC 和 REST 適用場景

REST和RESTful

REST(Representational State Transfer,表述性狀態轉移) 是一種軟體架構風格。REST提出了一組架構約束條件和原則,任何滿足 REST 約束條件和原則的架構,都稱為 RESTful 架構。

微服務之間需要相互通信以完成特定的業務處理,在典型的客戶端-服務端設計模型中,客戶端和服務端通通過消息請求-響應的方式交互協作,REST 就是這樣一套微服務之間交互接口的設計約束和原則規範。

乍一看 REST「表述性狀態轉移」每個字都認得,連起來不知道什麼意思。也難怪,這是作者 Roy Thomas Fielding 在他的博士論文裡提出的概念,論文自然都是學術用語,不過感興趣的同學可以去看看作者論文原文,地址我貼出來:https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

今天 lemon 用大白話幫你透徹理解這個概念,我們把「表述性狀態轉移」掰開來看,先搞明白什麼是「表述性」,什麼是「狀態轉移」。

表述性

「表述性」其實是缺少了主語的,主語是「資源」。完整的描述是「資源表述性」,也就是「資源的描述」。在網絡通信中用什麼描述資源呢?沒錯就是 URI(Uniform Resource Identifier,統一資源標識符)。

這裡有幾個近義詞先給大家先科普一下:

URI 是統一資源標識符,用來唯一的標識一個資源。

URL 是統一資源定位器,它是一種具體的 URI,即 URL 可以用來標識一個資源,而且還指明了如何定位這個資源,URL 是 URI 的子集。

URN 統一資源命名,是通過名字來標識資源。URN也是 URI 的子集。

URI-URL-URN關係

在 HTTP 協議中用 URL 標識資源,也就是瀏覽器地址欄你看到的那一串網址。

地址欄URL

資源表述性

為了說明「資源描述性」接口設計的優點,我們來做一個接口設計方法的對比,舉個慄子就清楚了。

傳統的接口設計

先來看下傳統的網絡通信模式是怎麼樣的。假設lemon這個人物對象,在服務端的存儲形式是一個c++的class類型存儲。

下面的過程展示,客戶端發送請求服務端創建一個 lemon 對象的過程。

  1. 服務端定義存儲結構頭文件 lemon.h

class lemon{  string name;  string address;  uint64 phone;}

  1. 客戶端代碼引用服務端定義的lemon.h,「互相引用頭文件,增加了服務耦合性!」
  2. 客戶端初始化一個 lemon 實例並序列化後通過網絡接口發送給服務端。

class lemon lm;lm.name = &34;;lm.address = &34;;lm.phone = 18666666666;

  1. 服務端接收消息,反序列化,存儲傳輸過來的 lemon 對象
資源表述性接口設計

lemon 這個服務內部的對象,對外表現可以用一張圖片來表示,也可以用包含lemon 的姓名、地址、電話等信息的 xml 或 json 格式的數據表示。

{name : &34;,address:  &34;,phone  :  18666666666}

<?xml version=&34; encoding=&34; ?> <name>lemon</name> <address>ShenZhen</address> <phone>18666666666</phone>

也就是說,lemon 這個「資源」在服務內部的存放形式對外不可見,外界客戶端發起請求可以用不同的資源表述格式來獲取服務端的資源。

(如果伺服器會說話,他內心os 大概是這樣的: 客戶端你不用管我是如何保存這個對象的,只要你說的清楚想要什麼對象,只管發來請求便是!)。

這樣做最顯然的好處是,減少了服務之間的耦合。客戶端訪問服務資源之前不需要知道資源在服務端的具體存儲格式,只需描述資源形式即可修改、創建、更新、刪除服務端的資源。

狀態轉移

搞懂了「資源描述性」接下來看下什麼是「狀態轉移」?狀態轉移就是客戶端通過一系列請求動作,推動服務端的資源狀態發生變化,資源的狀態可以在「創建-修改-查看-刪除」之間轉移。

資源狀態轉移

資源狀態的變化在宏觀上的反應就是業務流程推進。打個比方,你去銀行系統開戶、查餘額、銷戶,這個過程你推動了你的銀行帳戶這個「資源」經歷了不同的狀態轉移讓你完成了不同的業務操作。

REST的約束條件

協議選擇

REST 本身並沒有提到底層應該使用什麼協議,日常實踐案例中最常用的是基於 HTTP 的 RESTful 實現。

這是因為 HTTP 協議自帶的動詞 GET/POST/PUT/DELETE 可以作為推動狀態轉移的方法,另外HTTP 的制定了規範的狀態碼。還有其他的一些 HTTP 特性,這些特性使得在HTTP 之上實現 REST 要簡單得多,而如果使用其他協議的話,就需要自己實現這些特性。

請求規範

RESTful 架構中,發生狀態轉換的是「資源」,所以URI 中一般只能包含代表「資源」的名詞,並且推薦是複數,而不應該在 URI 中包對資源進行操作的動詞。

對資源執行的CURD「增刪改查」動作應該在HTTP請求方法的GET/POST/PUT/DELETE中體現。

符合REST規範的寫法:

POST http://www.test.com/lemon // 創建Get http://www.test.com/lemon // 查詢PUT http://www.test.com/lemon // 修改DELETE http://www.test.com/lemon //刪除

不符合REST規範的寫法:

POST http://www.test.com/Createlemon // 創建POST http://www.test.com/Querylemon // 查詢POST http://www.test.com/Modifylemon // 修改POST http://www.test.com/Deletelemon //刪除

狀態碼

服務端消息響應攜帶狀態碼,指示客戶端進行下一步處理。符合 RESTfull 規範的接口返回狀態碼都是通用的,不需要額外約定,利用HTTP Status Code 狀態碼 表示請求處理結果,降低了微服務間互操作成本。

狀態碼 狀態碼含義 2xx 成功,操作被成功接收並處理 3xx 重定向,需要進一步的操作以完成請求 4xx 客戶端錯誤,請求包含語法錯誤或無法完成請求 5xx 伺服器錯誤,伺服器在處理請求的過程中發生了錯誤

下面是常見的HTTP狀態碼:

  • 200 - 請求成功
  • 301 - 資源(網頁等)被永久轉移到其它URL
  • 404 - 請求的資源(網頁等)不存在
  • 500 - 內部伺服器錯誤

無狀態

RESTful接口要求是「無狀態」。無狀態指的是任意一個Web請求必須完全與其他請求隔離,當客戶端發起請求時,消息本身包含了服務端識別這一請求上下文所需的全部信息。

無狀態不是真的沒有狀態

接口「無狀態」更確切的說是服務端無狀態,整個會話還是需要狀態維持的。要完成一個業務流程,一般客戶端與服務端需要多次的消息交互,我們知道HTTP 協議是「無狀態協議」,這就需要服務端能夠識別幾個獨立 HTTP 請求的「狀態信息」,從而將他們關聯到一個業務流程中。

還是舉例子銀行系統取款的例子:

  • 用戶lemon要登錄銀行系統,首先需要在登錄頁面輸入用戶名和密碼,這時候產生一個登錄請求
  • 服務端收到登錄請求,執行登錄邏輯並返回操作結果
  • lemon登錄之後點擊取款100萬,產生一個取款請求
  • 服務端收到取款請求,執行取款邏輯並返回操作結果

取款業務流程

這裡有個問題,服務端在不同時間點收到登錄請求和取款請求,這兩個請求都是用戶 lemon 產生的,如果不在技術層面做對獨立的 HTTP 請求做關聯的話,服務端就無法知道這兩個請求其實是都是用戶lemon 「取款業務」的組成部分。

技術方案

服務端要能識別請求的「狀態信息」,有兩種技術方案:

  1. Session 方式。服務端保存會話狀態,客戶端每次請求攜帶session-id。 服務端維護一個會話狀態信息列表,用session-id唯一標識一個狀態信息,session-id一般包含在HTTP響應的Set-Cookie頭部返回給客戶端,後續客戶端請求攜帶包含session-id信息的cookie頭部,服務端解析cookie取出session-id,去維護的狀態列表中取回該消息對應的狀態信息,這樣就把無狀態的HTTP變成有狀態的了。

session會話

  1. Token 方式。服務端不保存會話狀態,客戶端每次請求都攜帶完整的會話狀態信息(一般是加密的)給服務端。 Token也稱作是「令牌」或臨時證書籤名,狀態信息都被加密到token中,這樣每當伺服器收到請求後解密token就能獲取該請求對應的狀態信息,也就能把不同的請求消息關聯到同一個業務流程中來,和session方式有類似的效果,只不過這次的狀態信息不保存在服務端。

Token會話

以上兩種實現中,第一種 Session 方式是有狀態的,第二種 Token 方式是無狀態的。

如果你要實現 RESTful 接口最好按第二種技術方案實現,當然要實現無狀態也還有其他方式,思路都是「服務端不保持會話狀態」就對了。

為什麼要無狀態

為了高可用性和負載均衡需求,多個微服務通過負載均衡實現分布式集群化部署,集群中每個服務都是獨立和對等的。如果伺服器在收到客戶端請求之時不可用或者宕機,無狀態請求可以由任何其他可用伺服器處理並作出應答,這在分布式應用中非常重要。

REST無狀態接口

想像一下如果服務端保存狀態,一個事務內的每個請求都必須落到同一臺伺服器去處理,這就失去了分布式的意義和優勢。

所以, RESTful 接口要求是無狀態的,是為了更好的適應分布式業務場景,發揮微服務集群優勢。

REST 和 RPC

這兩個概念經常出現在微服務架構設計中,REST 是一種軟體架構接口設計風格,RPC 是一種計算機通信協議,看起來是兩個不同的概念,沒法比較。

但是有些書中把它們放在一起比較,真要比較的話,我個人傾向於把 REST 具體化為一種基於HTTP 並按照 REST 約束設計的通信協議,這樣兩個通信協議才有比較性。

回顧下RPC

RPC (Remote Procedure Call)遠程過程調用是一個計算機通信協議。我們一般的程序調用是本地程序內部的調用,RPC允許你像調用本地函數一樣去調用另一個程序的函數,這中間會涉及網絡通信和進程間通信,但你無需知道實現細節,RPC框架為你屏蔽了底層實現。RPC 是一種伺服器-客戶端Client/Serv er模式,經典實現是一個通過發送請求-接受回應進行信息交互的系統。

適用場景

很多 RPC 框架提供的消息傳輸都是基於二進位的,比如Thrift、Protocol buffers。這樣做的好處是消息結構比較緊湊,對於頻繁調用或者大流量、低時延要求的應用場景,能夠顯著減少網絡開銷;另一個約束是某些 RPC 框架有很強的技術耦合性,比如 Dubbo 只能用於 java 技術棧。綜上,RPC 「更加適用於系統內部微服務之間的高效通信。」

RESTful接口由於提供了統一的基於 HTTP的 REST 設計標準,只需 web 框架支持 HTTP 協議,並設計RESTful 風格的接口即可,極大的方便了第三方服務接入調用,「適合用於微服務系統對外暴露的接口設計標準。」

寫在最後

本文是微服務架構設計中接口選型的一個小方面,很多人會覺得現在工作面試,不管是大廠還是小公司,都是面試造飛機,工作擰螺絲。個人認為即使你在入職之後接觸不到架構方面的工作,也要有一顆架構的心,高度決定認知,如果只盯著手上的那顆螺絲那和鹹魚有什麼區別?

老規矩。感謝各位的閱讀,文章的目的是分享對知識的理解,技術類文章我都會反覆求證以求最大程度保證準確性,若文中出現明顯紕漏也歡迎指出,我們一起在探討中學習。

好了,今天的技術分享就到這裡,本文是後端開發微服務設計系列的第二篇,這個系列應該還會繼續更新,我們下期再見。

文章每周持續更新,可以微信搜索公眾號「 後端技術學堂 」提前看,關注後回復「資料」有我給你準備的各種編程學習資料,我們下期見!

更多內容,點下方「了解更多」連結

相關焦點

  • 面試都在問的微服務、RPC、服務治理...一文幫你徹底搞懂!
    ❝2014年,Martin Fowler 與 James Lewis 共同提出了微服務的概念,定義了微服務是由以單一應用程式構成的小服務,自己擁有自己的行程與輕量化處理,服務依業務功能設計,以全自動的方式部署,與其他服務使用 HTTP API 通信。
  • 面試被吊打!Spring Boot 面試,一個問題就幹趴下了
    同時隨著微服務概念的推廣和實踐,Spring Boot的精簡理念又使其成為Java微服務開發的不二之選,也可以說,Spring Boot其實就是為了微服務而生的Java web框架。都是通過「約定優於配置「的設計思路來設計的,Spring Boot Starter 在啟動的過程中會根據約定的信息對資源進行初始化;Spring Boot Jpa 通過約定的方式來自動生成 Sql ,避免大量無效代碼編寫。具體詳細可以參考:Spring Boot 為什麼這麼火?問:Spring Boot Starter 的工作原理是什麼?
  • 2020年的Java程式設計師面試三件套:多線程+算法+微服務
    ,這三本書籍是小編用禿頭為代價,精心研究挑選出來的,讓大家對這三個知識框架有個基本輪廓,應對個面試還是沒什麼問題的;我之前也是溫水煮青蛙,出去面試了才被教各種做人!比如之前面試某 AI 獨角獸前兩面幾乎就是全程算法題,都沒怎麼問別的,你不準備的話幾乎是 100%要掛掉。從我之前的面試經驗來看,這幾年算法面試難度明顯提高。
  • 基於.NET CORE微服務框架surging示例 (開源)
    隨著歲月的成長,技術也從原來的三層設計到現在的領域驅動設計,從原來的關係型資料庫SQL 2000到現在的NOSQL (mongodb,couchbase,redis),從原來基於SOAP協議的webservice到現在基於restful 協議的web api,wcf,再到現在rpc微服務。
  • 女後端開發工程師之面試篇
    前天面試了一個女程式設計師,女孩子做開發還是比較少的,尤其是從市場營銷專業轉做IT,一下子引起我的好奇心。首先做自我介紹,女孩子講得都還不錯,近期主要做的也是微服務項目,能把微服務的組件跟項目經歷結合起來,從開發到服務得部署,一起出發服務熔斷等。沒有相關開發經驗,編是編不出來的。 我問了下微服務項目中碰到了什麼坑,她也直說部署的服務相對比較多,接口的數據調用如果沒有在開發開始前確定好,後面肯定會花不少時間去做修改的。
  • RPC 好,還是 RESTful 好?
    這一層主要就是傳輸這些二進位數據。實際應用過程中,五層協議結構裡面是沒有表示層和會話層的。應該說它們和應用層合併了。我們應該將重點放在應用層和傳輸層這兩個層面。因為HTTP是應用層協議,而TCP是傳輸層協議。好,知道了網絡的分層模型以後我們可以更好地理解為什麼RPC服務相比HTTP服務要Nice一些!
  • 我手寫完RPC框架,成功幫助讀者斬獲阿里等大廠offer
    guide-rpc-framework 目前只實現了 RPC 框架最基本的功能,一些可優化點都在下面提到了,有興趣的小夥伴可以自行完善。通過這個簡易的輪子,你可以學到 RPC 的底層原理和原理以及各種 Java 編碼實踐的運用。你甚至可以把 guide-rpc-framework 當做你的畢設/項目經驗的選擇,這是非常不錯!
  • 500+篇Java乾貨技術文章整理|資源|書單|工具|面試...
    Java工程師學習指南(入門篇)Java工程師學習指南(初級篇)Java工程師學習指南(中級篇)Java工程師學習指南(完結篇)想了解Java後端學習路線?你只需要這一張圖!終於有人把最適合學習算法的書單找出來了,面試必備!學好程式設計師必知必會的數據結構,這一份書單你值得擁有!你真的以為計算機網絡不重要嗎,這份書單幫你搞定相關面試題!這一份MySQL書單,可以幫你搞定90%以上的面試題!送你一份Redis書單,以後使用緩存的問題不用再問我啦!
  • 通過阿里的三面,我總結出來了這些Java面試的規律
    由於分布式相關場景我沒有接觸過,因此面試官一直誘導我去設計實現一個分布式事務。資料庫樂觀鎖和悲觀鎖。如何實現一個樂觀鎖。消息隊列使用場景,Kafka的架構以及原理。什麼是restful api,和rpc調用有什麼區別。單例的幾種寫法。volatile關鍵字有什麼作用。
  • 2020年最新巨作,Spring微服務架構設計,堪稱面試必備
    ,先搞定架構設計吧第9章用Docker容器化微服務第10章用Mesos和Marathon擴展容器化的微服務第11章微服務開發生命周期如果需要這本書的話,可以關注我轉發文章之後私信回復【筆記】100%免費獲取到
  • Tencent內部瘋傳「Java面試題庫」,看完直呼666
    就目前的招聘網際網路Java程式設計師的情況來看,面試造火箭,工作擰螺絲的情況非常常見,很多公司面試都會問到源碼,原理。所以很多小夥伴在面試之前刷一刷面試題,為每次面試做好準備!小編目前在這家公司已經任職超過7年了, 在此期間,也面試過近100人,所以總結出一整套面試題庫,涵蓋了網際網路大部分知識點,如果你能夠徹底掌握的話,只要硬體能力達到,拿到對標P7的offer不是問題!
  • 三面阿里java後臺開發崗總結:進阿里必看這份究極面試文檔
    由於分布式相關場景我沒有接觸過,因此面試官一直誘導我去設計實現一個分布式事務。資料庫樂觀鎖和悲觀鎖。如何實現一個樂觀鎖。消息隊列使用場景,Kafka的架構以及原理。什麼是restful api,和rpc調用有什麼區別。單例的幾種寫法。volatile關鍵字有什麼作用。
  • 騰訊三面終拿Offer,關於redis,高並發,分布式,微服務一鍵領取
    這一個多月刷了挺多題,也看了許多筆經面經,三面大概九十分鐘,問的東西很全面,需要做充足準備。回來之後把這些題目做了一個分類並整理出答案(強迫症的我~狂補知識~)分為redis緩存,高並發,分布式,微服務等,接下來分享一下我的這騰訊面試的面經加上一些我的學習筆記。
  • 面試不會微服務沒關係,跟著我4天學會微服務
    如今微服務倍受關注:文章、博客、社交媒體和會議演講都在討論微服務。微服務正在迅速朝著加德納技術成熟度曲線(Gartner Hype cycle)的高峰前進。與此同時,也有持懷疑態度的軟體社區人員認為微服務沒什麼新鮮可言。反對者聲稱它的思想只是面向服務架構(SOA)的重塑。然而,無論是炒作還是懷疑,不可否認,微服務架構模式有非常明顯的優勢 —— 特別是在實施敏捷開發和複雜的企業應用交付方面。
  • 徹底搞懂 etcd 系列文章之etcd 事務 API
    etcd 在微服務和 Kubernates 集群中不僅可以作為服務註冊與發現,還可以作為 key-value 存儲的中間件。《徹底搞懂 etcd 系列文章》將會從 etcd 的基本功能實踐、API 接口、實現原理、源碼分析,以及實現中的踩坑經驗等幾方面具體展開介紹 etcd。預計會有 20 篇左右的文章,筆者將會每周持續更新,歡迎關注。
  • 應屆畢業生看過來!Java面試經典77問,看完離工作就不遠了
    面試前看完這份我精心整理的BAT一線網際網路企業的Java面試幾乎必問的77道面試題,對你的面試絕對是有很大的幫助的。有需要這份「Java面試經典77問」資料的朋友可以私信我口令「應屆生求職」即可100%免費領取的!文末有大家感興趣的小福利等著大家,看到最後的人有福啦[酷]!
  • Java面試通關要點匯總集(基礎篇+核心篇+框架篇+微服務篇)
    基礎篇基本功面向對象的特徵final, finally, finalize 的區別int 和 Integer 有什麼區別重載和重寫的區別抽象類和接口有什麼區別說說反射的用途及實現說說自定義註解的場景及實現HTTP 請求的 GET 與 POST 方式的區別session 與 cookie 區別session 分布式處理JDBC 流程MVC 設計思想
  • 微服務、並發編程、開源框架、分布式,高效緩存,面試你還缺什麼
    ,得到一個通用的點: 傳統的行業需求還在問,但是問的難度加深,新型的技術需求反而詢問更多,尤其是實際操作經驗的詢問但是說實話,不是說在座的所有人啊,我覺得大部分人很多技術會或者說在自己的pc端玩過,但是這跟真實生產環境還有一些區別的,哪怕有些朋友會用做壓測,但是性能這個玩意,我想大家都懂
  • 20道你必須要背會的微服務面試題,面試一定會被問到
    寫在前面:在學習springcloud之前大家一定要先了解下,常見的面試題有那塊,然後我們帶著問題去學習這個微服務技術,那麼就會更加理解springcloud技術。如果你已經學了springcloud,那麼在準備面試的時候,一定要看看看這些面試題。