兩個獨立的應用程序需要中介程序才能相互通信。 因此,開發人員經常建立橋梁-應用程序編程接口-來允許一個系統訪問另一個系統的信息或功能。
為了快速,大規模地集成應用程序,使用協議和/或規范來定義通過導線傳遞的消息的語義和語法的API。 這些規范構成了API體系結構。
隨著時間的流逝,已經發布了不同的API架構樣式。 它們每個都有自己的標準化數據交換模式。 選擇的余地引發了關于哪種建筑風格最好的爭論。
> API styles over time, Source: Rob Crowley
如今,許多API使用者將REST稱為" REST和平",并為GraphQL歡呼,而十年前,REST取代SOAP成為贏家,這是一個相反的故事。 這些觀點的問題在于,他們只是一方面選擇一種技術,而不是考慮其實際屬性和特性如何與當前情況相匹配。
在本文中,我們將保持客觀,并按外觀順序討論四種主要的API樣式,比較它們的優缺點,并重點介紹每種情況下最適合的情況。
> Four major API styles compared
遠程過程調用(RPC):在另一個系統上調用功能
遠程過程調用是一種允許在不同上下文中遠程執行功能的規范。 RPC擴展了本地過程調用的概念,但將其放在HTTP API的上下文中。
最初的XML-RPC存在問題,因為很難確保XML有效負載的數據類型。 因此,后來RPC API開始使用更具體的JSON-RPC規范,該規范被認為是SOAP的更簡單替代方案。 gRPC是google在2015年開發的最新RPC版本。gRPC可插拔支持負載平衡,跟蹤,運行狀況檢查和身份驗證,非常適合連接微服務。
RPC如何運作
客戶端調用遠程過程,將參數和其他信息序列化為消息,然后將消息發送到服務器。 在接收到消息時,服務器反序列化其內容,執行所請求的操作,然后將結果發送回客戶端。 服務器存根和客戶端存根負責參數的序列化和反序列化。
> Remote Procedure Calling Mechanism, Source: Guru99
RPC優點
簡單直接的互動。 RPC使用GET來獲取信息,并使用POST進行其他所有操作。 服務器與客戶端之間的交互機制歸結為調用端點并獲得響應。
易于添加的功能。 如果對API提出了新要求,我們可以輕松添加另一個執行此要求的端點:1)編寫一個新函數并將其扔到端點后面; 2)現在,客戶可以訪問該端點并獲取符合設置要求的信息 。
高性能。 輕量級有效負載在網絡上變得容易,可提供高性能,這對于共享服務器和在工作站網絡上執行的并行計算非常重要。 RPC能夠優化網絡層,并通過每天在不同服務之間發送大量消息來使其變得非常高效。
RPC缺點
與底層系統緊密耦合。 API的抽象級別有助于其可重用性。 它與基礎系統越緊密,對其他系統的可重用性就越差。 RPC與基礎系統的緊密耦合不允許在系統功能和外部API之間建立抽象層。 這很容易引起安全問題,因為很容易將有關基礎系統的實施細節泄漏到API中。 RPC的緊密耦合使得可伸縮性要求和松散耦合的團隊難以實現。 因此,客戶端要么擔心調用特定端點的任何可能的副作用,要么嘗試弄清楚要調用的端點,因為它不了解服務器如何命名其功能。
發現性低。 在RPC中,無法對API進行自省或發送請求,也無法根據其請求開始理解要調用的函數。
功能爆炸。 創建新功能非常容易。 因此,我們不用編輯現有功能,而是創建新功能,最后添加大量難以理解的重疊功能。
RPC用例
RPC模式在80年代左右開始使用,但這并不會自動使其過時。 諸如Google,Facebook(Apache Thrift)和Twitch(Twirp)之類的大公司正在內部使用RPC高性能變量來執行非常高性能,低開銷的消息傳遞。 他們龐大的微服務系統要求內部通信在安排短消息時保持清晰。
命令API。 RPC是將命令發送到遠程系統的正確選擇。 例如,Slack API非常注重命令:加入頻道,離開頻道,發送消息。 因此,Slack API的設計人員以類似于RPC的樣式對其進行了建模,使其小巧,緊湊且易于使用。
內部微服務的客戶特定API。 由于在單個提供商和使用者之間進行了直接集成,我們不想像REST API那樣花費大量時間通過網絡傳輸大量元數據。 憑借高消息速率和消息性能,gRPC和Twirp是微服務的強大案例。 在后臺使用HTTP 2,gRPC能夠優化網絡層并使其非常高效,每天在不同服務之間發送大量消息。 但是,如果您不是要著眼于提高網絡性能,而是要在發布高度獨特的微服務的團隊之間建立穩定的API聯系,REST將確保這一點。
簡單對象訪問協議(SOAP):使數據作為服務可用
SOAP是XML格式的高度標準化的Web通信協議。 SOAP在Microsoft于XML-RPC發行一年后發布,從中繼承了很多東西。 當REST緊隨其后時,它們首次并行使用,但很快REST贏得了流行度競賽。
SOAP如何工作
XML數據格式拖累了許多形式。 配合龐大的消息結構,它使SOAP成為最冗長的API樣式。
SOAP消息包括:
· 包含請求或響應的正文
· 標頭(如果消息必須確定任何具體要求或額外要求),以及
· 故障通知在整個請求處理過程中可能發生的任何錯誤。
> An example of the SOAP message. Source: IBM
SOAP API邏輯以Web服務描述語言(WSDL)編寫。 該API描述語言定義了端點并描述了可以執行的所有過程。 這允許不同的編程語言和IDE快速建立通信。
SOAP支持有狀態和無狀態消息傳遞。 在有狀態的情況下,服務器存儲接收到的信息可能非常重。 但這對于涉及多方和復雜交易的操作是合理的。
SOAP優點
與語言和平臺無關。 創建基于Web的服務的內置功能允許SOAP處理通信并做出與語言和平臺無關的響應。
綁定到各種傳輸協議。 SOAP在傳輸協議方面很靈活,可以適應多種情況。
內置錯誤處理。 SOAP API規范允許返回帶有錯誤代碼及其說明的Retry XML消息。
許多安全擴展。 SOAP與WS-Security協議集成,可滿足企業級事務質量。 它在事務內部提供隱私和完整性,同時允許在消息級別進行加密。
> SOAP message-level security: authentication data in the header element and encrypted body
SOAP缺點
如今,由于多種原因,許多開發人員對必須集成SOAP API的想法感到不安。
僅XML。 SOAP消息包含大量元數據,并且僅支持請求和響應的詳細XML結構。
重量級的。 由于XML文件的大小,SOAP服務需要很大的帶寬。
狹義的知識。 構建SOAP API服務器需要深入了解所有涉及的協議及其嚴格的規則。
乏味的消息更新。 需要額外的努力來添加或刪除消息屬性,嚴格的SOAP模式會減慢采用速度。
SOAP用例
目前,SOAP體系結構最常用于企業內部或與其信任的合作伙伴的內部集成。
高度安全的數據傳輸。 SOAP的嚴格結構,安全性和授權功能使其成為執行API與客戶端之間的正式軟件合同,同時又遵守API提供者與API使用者之間的合法合同的最合適的選擇。 這就是為什么金融組織和其他公司用戶選擇SOAP的原因。
REST:使數據可用作資源
REST是一種不言自明的API架構樣式,由一組架構約束定義,旨在供許多API使用者廣泛采用。
當今最常見的API樣式最初是由Roy Fielding于2000年在其博士論文中描述的。 REST使服務器端數據可用,以簡單格式(通常為JSON和XML)表示它。
REST如何工作
REST的定義不像SOAP那樣嚴格。 RESTful體系結構應遵守六個體系結構約束:
· 統一接口:無論設備或應用程序類型如何,都可以采用統一的方式與給定服務器進行交互
· 無狀態:處理請求本身所包含的請求的必要狀態,并且服務器不存儲與會話相關的任何內容
· 快取
· 客戶端-服務器體系結構:允許雙方的獨立發展
· 應用程序的分層系統
· 服務器向客戶端提供可執行代碼的能力
實際上,某些服務僅在一定程度上是RESTful的。 它們以RPC樣式為核心,將較大的服務分解為資源,并有效地使用HTTP基礎結構。 但是關鍵部分是使用超媒體(又稱HATEOAS),是超文本作為應用程序狀態引擎的縮寫。 基本上,這意味著REST API在每個響應中都提供元數據鏈接,該元數據鏈接到有關如何使用該API的所有相關信息。 這樣便可以使客戶端和服務器脫鉤。 結果,API提供者和API使用者都可以獨立發展,而不會阻礙他們的交流。
> Richardson Maturity Model as a goalpost to achieving truly complete and useful APIs, Source: Krist
" HATEOAS是REST的關鍵功能。 真正使REST成為REST的原因。 由于大多數人不使用HATEOAS,因此實際上是在使用HTTP RPC,"這是Reddit上表達的一些激進觀點。 實際上,HATEOAS是REST的最成熟版本。 但是,要實現比當今通常使用和構建的API客戶端更為先進和智能的API客戶端要困難得多。 因此,即使是當今非常好的REST API也不一定總是做到這一點。 這就是為什么HATEOAS主要用作RESTful API設計的長期開發的愿景。
當服務實現REST的某些功能和RPC的某些功能時,在REST和RPC之間確實可能存在一個灰色區域。 REST基于資源或名詞,而不是基于動作或動詞。
> Opposing operations in verb-centric RPC to the ones in noun-centric REST
在REST中,使用GET,POST,PUT,DELETE,OPTIONS和PATCH等HTTP方法完成操作。
> Source: Thomas Davis
REST的優點
客戶端和服務器解耦。 REST盡可能使客戶端和服務器脫鉤,與RPC相比,REST可以提供更好的抽象性。 具有抽象級別的系統能夠封裝其詳細信息,以更好地標識和維持其屬性。 這使得REST API足夠靈活,可以隨著時間的推移而發展,同時保持穩定的系統。
可發現性。 客戶端與服務器之間的通信描述了所有內容,因此不需要外部文檔即可了解如何與REST API進行交互。
緩存友好。 REST重用了許多HTTP工具,是唯一一種可以在HTTP級別上緩存數據的樣式。 相反,在任何其他API上進行緩存實現將需要配置其他緩存模塊。
多種格式支持。 支持多種格式用于存儲和交換數據的能力是REST當前成為構建公共API的主要選擇的原因之一。
REST缺點:
沒有單一的REST結構。 沒有建立REST API的正確方法。 如何對資源進行建模以及要對哪些資源進行建模將取決于每種情況。 這使得REST在理論上很簡單,但在實踐中卻很困難。
大負載。 REST返回很多豐富的元數據,以便客戶端可以僅從響應中了解有關應用程序狀態的所有必要信息。 對于具有大量帶寬容量的大型網絡管道而言,這種聊天狀態并不重要。 但這并非總是如此。 這是Facebook在2012年提出GraphQL樣式的關鍵驅動因素。
過度獲取和不足獲取問題。 REST響應包含的數據過多或不足,通常會導致需要另一個請求。
REST用例
管理API。 專注于管理系統中對象并面向許多使用者的API是最常見的API類型。 REST幫助此類API具有強大的可發現性,良好的文檔編制,并且非常適合此對象模型。
簡單的資源驅動型應用程序。 REST是一種非常有用的方法,用于連接不需要查詢靈活性的資源驅動型應用。
GraphQL:僅查詢所需的數據
它需要多次調用REST API才能返回所需的人員。 因此,GraphQL被發明為改變游戲規則的人。
GraphQL是一種語法,描述了如何進行精確的數據請求。 對于具有許多相互引用的復雜實體的應用程序數據模型而言,實現GraphQL是值得的。
> How to retrieve only the needed data from the GraphQL endpoint, Source: Mohit Tikoo
如今,GraphQL生態系統正在通過庫和強大的工具(如Apollo,GraphiQL和GraphQL Explorer)進行擴展。
GraphQL如何工作
GraphQL從構建模式開始,該模式是對您可以在GraphQL API中進行的所有查詢及其返回的所有類型的描述。 模式構建非常困難,因為它需要使用模式定義語言(SDL)進行強類型化。
在查詢之前具有架構,客戶端可以驗證其查詢,以確保服務器能夠對其進行響應。 在到達后端應用程序時,將針對整個模式解釋GraphQL操作,并使用前端應用程序的數據進行解析。 該API向服務器發送一個龐大的查詢后,會返回一個JSON響應,其中包含我們所需數據的確切形狀。
> Query execution in GraphQL, Source: Jonas Helfer
除了RESTful CRUD操作之外,GraphQL的訂閱還允許來自服務器的實時通知。
GraphQL的優點
鍵入的架構。 GraphQL會提前發布其功能,從而提高其可發現性。 通過將客戶端指向GraphQL API,我們可以找出可用的查詢。
非常適合類似圖形的數據。 數據關系很深,但不適合平面數據。
沒有版本控制。 版本控制的最佳做法是根本不對API進行版本控制。
REST提供了多個API版本,而GraphQL使用的是一個不斷發展的版本,它可以持續訪問新功能,并有助于提供更清潔,更可維護的服務器代碼。
詳細的錯誤消息。 GraphQL以類似于SOAP的方式提供發生錯誤的詳細信息。 它的錯誤消息包括所有解析器,并引用發生故障時的確切查詢部分。
靈活的權限。 GraphQL允許選擇性地公開某些功能,同時保留私人信息。 同時,REST體系結構不會部分顯示數據。 全部或全無。
GraphQL的缺點
性能問題。 GraphQL權衡了復雜性。 一個請求中的嵌套字段太多會導致系統過載。 因此,對于復雜的查詢,REST仍然是更好的選擇。
緩存復雜度。 由于GraphQL不再使用HTTP緩存語義,因此需要自定義緩存工作。
很多預開發教育。 由于沒有足夠的時間來了解GraphQL利基操作和SDL,因此許多項目決定采用眾所周知的REST路徑。
GraphQL用例
移動API。 在這種情況下,網絡性能和單個消息有效負載優化很重要。 因此,GraphQL為移動設備提供了更有效的數據加載。
復雜的系統和微服務。 GraphQL能夠隱藏其API背后的多個系統集成的復雜性。 從多個位置聚合數據,它將它們合并為一個全局模式。 這對于隨時間推移而擴展的舊式基礎結構或第三方API尤其重要。
哪種API模式最適合您的場景?
每個API項目都有不同的要求和需求。 通常,架構選擇取決于
· 使用的編程語言
· 您正在開發的環境,以及
· 您必須保留的人力和財力資源。
知道了每種設計風格的所有權衡之后,API設計人員可以選擇最適合該項目的一種。
由于RPC緊密耦合,因此可用于內部微服務,但對于強大的外部API或API服務而言,它不是一種選擇。
SOAP很麻煩,但是其豐富的安全功能對于計費操作,預訂系統和付款仍然是不可替代的。
REST具有API的最高抽象度和最佳建模。 但是在網絡和聊天環境中,這往往會比較沉重-如果您正在使用移動設備,這將是不利的一面。
GraphQL在數據獲取方面邁出了一大步,但并不是每個人都有足夠的時間和精力來掌握它。
歸根結底,嘗試一些具有特定樣式的小型用例,并查看它是否適合您的用例并解決您的問題是有意義的。 如果可以,請嘗試擴展并查看它是否適合更多用例。
最初發布于AltexSoft技術博客"比較API體系結構樣式:SOAP vs REST vs GraphQL vs RPC"
(本文翻譯自Sanjeet Chatterjee的文章《Comparing API Architectural Styles: SOAP vs REST vs GraphQL vs RPC》,參考:https://levelup.gitconnected.com/comparing-api-architectural-styles-soap-vs-rest-vs-graphql-vs-rpc-84a3720adefa)