持续演进,克服“REST缺乏”
本文關鍵點
在過去的幾年中,軟件開發社區中出現了越來越多的反REST觀點。然而,替代技術經常出現在特定的上下文中,它們呈現出優點和缺點往往與特定用例相關。
REST崛起本身就是由一種錯誤的二分法導致的,當時SOAP扮演了反面角色。SOAP試圖提供一種通過Web協議打通隧道的方法,而REST方法則擁抱了這種方法。
軟件工程行業不應該尋求替代REST,而應該在開發新協議技術優勢的同時構建成熟的REST生態,從而謀求更進一步的發展。
新的API協議(如GraphQL、gRPC和Apache Kafka),作為受REST啟發的HTTP API的替代品,越來越受到歡迎。本文認為在一對一協議中體現不出REST范式的優勢。軟件工程行業不應該尋求替代REST,而應該在開發新協議技術優勢的同時構建成熟的REST生態,從而謀求更進一步的發展。
關于協議、范式和錯誤的二分法……
溫哥華人Tim Bray最近的博客文章“后REST”引起了業界的廣泛關注,這是有原因的。隨著Web API得到越來越多的應用,人們開始懷疑REST1是否是Web API的理想通信約定。除了開放Web通信最初的范圍之外,REST現在還用于提供Web應用程序數據、提供微服務間通信、促進基礎設施管理和自動化,甚至還用于消息傳遞、事件分發和流等異步模式。
Tim的文章很好地概括了REST的用法、它的局限性、一些新興的替代協議(GraphQL和gRPC),并推測了Web API通信的未來。雖然我大致上也贊同這篇文章的觀點,但我覺得這個話題不應僅限于這些,還有更多內容要談。換句話說,我不只是想看看什么可以替代REST,更希望我們考慮一下如何將REST的優勢與這些新協議的創新結合起來,從而為分布式軟件生態系統中的通信提供不斷演進的替代方案。
新的協議,舊的戰線,錯誤的二分法
在過去的幾年中,軟件開發社區中出現了越來越多的反REST觀點。許多文章都指著REST的局限性大發牢騷,并提出了替代的通信協議或方法。
在支持 GraphQL、gRPC、異步通信的聲音中,甚至更模糊的觀點中,經常看到“REST在x上不好,所以使用y代替”的說法。這些爭論差不多是這樣說的:
GraphQL比REST更好,因為它能夠讓API消費者控制接收到的數據,并能讓API提供者在服務器端聚合資源
gRPC(加上協議緩沖區)比REST更好,因為它是類型安全的,它通過二進制序列化優化了性能,并且能夠利用HTTP/2的能力
異步的通信(AMQP、Kafka等)優于同步的REST通信,因為它減少了阻塞和線程使用,從而提高了服務的自治
這些方法都是在特定的上下文中產生的。GraphQL是由Facebook創建的,在他們重新開發Facebook移動應用程序時,它也是其中的一部分。它是與Relay和React原生JavaScript框架一起使用的在線通信方法,本質上,這一方法是為應用程序提供特定的數據。許多GraphQL的公開支持者都傾向于數據中心和JavaScript,這一點大家都能想到。gRPC和協議緩沖區本來是谷歌內部使用的,并遵循與Kubernetes容器編制項目類似的公開路徑。許多的gRPC倡導者都集中在基于容器的應用程序之間的通信上,這一點大家也都能想到。互斥異步通信通常用于響應式系統或事件源的上下文中。在這些特定的上下文中,專門為其設計的方法自然會比那些更通用的REST方法具備一些優勢,這是件很自然而然的事。
為了捍衛REST,我們很容易流于表面去看待這些批評,并提出如下的觀點:
對于GraphQL案例,REST范式中完全沒有限制用戶選擇或資源聚合(在單個資源上使用靜態接口只是一種常見的實踐),而且大量信息表明,就算限制用戶選擇也有其自身的好處
對于gRPC,運行時優化不太可能是大多數分布式體系結構中的主要瓶頸,而gRPC的對嵌入類庫的需求(更不用說protobuf的枚舉結構)可能會導致無法預見的問題
對于異步,絕對有必要包括基于事件的場景,但是這些場景很可能是除同步模式(如查詢和命令)之外額外的
然而,在我看來,這些反面意見并不能說明一切。軟件工程是一個還缺乏REST的行業,我們經常過度簡化我們的問題,以證明過于簡單的解決方案是合理的。我們喜歡給“當紅的平臺”貼上標簽,以激勵大家迅速跳到一些新的安全地帶。因為批處理不好,所以實時處理就是好的。因為整體系統不好,所以微服務就是好的。在特定上下文中使用REST,它就變成了個反面典型,這就像上面的論調一樣,其實就是非好即壞的錯誤的二分法。也許我們應該研究研究另一個問題:REST是如何成為用于分布式計算中組件到組件網絡跳轉的默認通信方法的?讓我們穿越回最開始的時候。
REST的起源、興起和流行
Roy Fielding在2000年博士論文“架構風格與基于網絡的軟件架構的設計”中有一章定義了REST(表述性狀態轉移)。本篇論文的主要目的是“定義一個理解軟件架構的框架”……,以指導基于網絡的應用軟件的架構設計。在架構風格示例中,REST就包含其中,這些架構風格將萬維網的設計原則編寫成代碼,重點強調了接口的可演化性、可伸縮性和通用性。與上文列出的新方法的上下文相比,REST一開始的問題領域有著非常廣闊的空間。
在這廣闊的空間之中,其中一個想法非常流行,那就是在瀏覽器之外基于網絡共享數據和服務。軟件開發人員快速基于Fielding的工作成果并將其付諸實踐3。REST崛起本身就是由一種錯誤的二分法導致的,在當時SOAP扮演了反面角色。SOAP試圖提供一種通過Web協議打通隧道的方法,而REST方法則擁抱了這種方法。“REST是Web的一部分,而不僅僅是在Web上”,對于已經在構建基于Web的解決方案的軟件工程師來說,這一概念他們從直覺上更愿意直接去選擇它。
隨著SOAP和WS-*生態環境變得越來越復雜,由于REST的相對簡單性和可用性,使其勝出了。隨著時間的推移,JSON出于類似的原因取代了XML,成為Web API事實上的數據格式。隨著Web計算范式的使用擴展到新的場景(比如企業應用程序集成、云供應、數據倉庫查詢、物聯網等等),REST API采用的范圍也隨之擴展。
現在,如果針對每個特定的使用場景審視一翻,可能REST的適用性會存在一些弱點,或者會有一些看起來更理想的替代通信方法。但這么比較就忽視了REST所具備的廣泛性能力。由于REST的廣泛性,已經慣于使用AJAX調用的Web開發人員可以憑直覺掌握如何使用AWS的API來提供云基礎設施;基于Web的社交網絡的開發人員可以迅速為移動應用程序鋪設管道;企業級軟件的開發人員所能做到的大家就更為熟悉了,他們可以使新拆分的微服務相互通信。軟件工程是這樣一個領域:交付障礙往往是人為造成的,而不是機器。充分理解方法提供的價值,通常比技術最優化的利基解決方案對交付時間有更大的影響。
在REST生態系統中,這種廣泛性還帶來了健壯性。Swagger(現在是OpenAPI)作為元數據規范適時出現,成為一個有機的補充,它旨在幫助開發人員記錄、設計和使用API。OAuth為身份驗證和授權提供了一個可伸縮的、可轉換的框架。“API管理”作為一組特性出現,包括速率限制、動態路由、緩存等,實踐證明這些在提供REST API時非常有用。REST范式的全面性及其生態系統的成熟度表現出REST作為軟件系統中基于網絡的通信方法的最大價值。很可能,這種廣泛性更多地來自于REST成為“Web工作的方式”,而不是任何一個技術細節。
后Web范式中的通信
Web對軟件工程的影響再怎么強調都不為過。在REST興起的同時,軟件工程領域也涌現出了開源、敏捷、DevOps、領域驅動設計和微服務體系架構。這些運動中的每一個都得益于Web,它們不約而同地放大了軟件交付中人為因素的重要性。隨著云計算提供的靈活性和方便性,已經涌現出一種新的軟件工程范式,它的特征是持續運行、持續發展、松耦合的應用程序和服務。雖然Tim Bray將他的文章稱為“后-REST”,但也許這種新范式可以稱為“后-Web”。由于這種范式的特征與Fielding的REST的原始原則是一致的,因此舍棄REST從頭開始是沒有意義的。換句話說,忽視20年來的技術創新同樣是個很幼稚的做法。
那么REST的價值在這個新范式中如何演變呢?現在,越來越多的組織采用“API為上”的方法進行軟件開發,也就是說,強調在應用程序和服務中機器接口的設計與UI的設計同樣重要,并應借助這些API來解耦負責不同領域的團隊的開發工作。OpenAPI通常在這種方法中扮演重要角色,因為它是與實現無關的接口規范。根據后-Web范式,這對構建或修改軟件系統的各方面人員都有好處。目前已經有一個正在進行的項目,它是來自Fran Mendez的AsyncAPI ,其旨在為基于事件的交互帶來同樣的價值。沿著同樣的思路,Mike Amundsen和Leonard Richardson引入了ALPS規范來記述基于網絡的應用程序交互的語義。像這些成果有助于解決構建分布式系統的設計時的挑戰。
在云本地運行時中也有機會擴展REST的價值。向微服務的遷移引入了進程間通信(IPC)常常發生的網絡邊界問題。這些物理邊界可以刻意投影為業務領域邊界,以實現上面討論的人員利益。
但是,這存在一個潛在的運行時權衡,即額外的網絡延遲和服務調用鏈中出現部分故障的可能性。
服務網格模式為基于容器的系統解決了這些問題,它的特點是有一個“邊車”服務代理,由它處理應用組件之間所有基于網絡的通信。服務網格拓撲意味著,已經在應用程序容器及其相關的邊車之間重新引入了IPC。盡管如此,應用程序容器的開發人員仍然需要在代碼中特別指定網絡協議,因為服務代理通常不會更改代理消息的傳輸協議。
究竟,這些應用程序開發人員應該負責協議處理嗎?它們應該處理抽象的服務請求(查詢、命令、事件),讓服務代理處理協議映射、轉碼和傳輸嗎?這些問題值得商榷,REST API的通用設計時理解可以作為開始抽象的一個起點。這些只是REST的廣泛性可以用來幫助固化后-Web范式的兩個領域。
一個不怎么缺乏REST的未來
大肆炒作的技術趨勢經常吹噓它們如何用新方法取代了舊方法。在現實中,軟件工程通常是層疊進行演進的。每一個新的創新都為后續的一系列創新奠定了基礎。新的API協議(如GraphQL、gRPC和Kafka)將取代在某些分布式場景中使用基于資源、json編碼、HTTP傳輸的消息。然而,REST在分布式系統的發展中留下的遺產不應該只是與其實現細節相關的內容,而更多的應該是令它如此無處不在的相關特征:為通用連接性提供框架、將服務消費者與提供者分離、強調可用性和可訪問性。正是這些特征使得REST(最初定義為Web的體系結構樣式)成為軟件工程的后Web范式的基礎。
腳注
本文的目的不是討論REST的定義。術語“REST”將用于指代Fielding的原始定義以及HTTP上的CRUD風格的API。
有關REST/gRPC/GraphQL如何根據上下文決策的實際分析,請閱讀Phil Sturgeon的這篇博客。
…而且,在很早的時候,就已經不再滿足于將REST只是概括為HTTP上的CRUD了。請參閱這里。
回到SOAP的二分法,一邊是這種有機標準的開發,一邊是W3C和OASIS標準的爆炸式增長,它們形成了鮮明的對比,這兩個標準出現在2000年初Web服務繁榮的高峰時期。
感謝Mike Amundsen、Erik Wilde、Irakli Nadareishvili和Ronnie Mitra找到了本文中列出的“REST的歷史”資源。
關于作者
Matt McLarty是一位卓有經驗的軟件架構師,領導博通公司CA 科技的API Academy團隊。他與組織緊密合作,設計和實現創新的企業級API和微服務解決方案。在軟件供應商和客戶端的集成和實時事務處理領域,他有著廣泛的工作經驗。Matt最近與人合著了O 'Reilly的書《微服務體系結構和微服務API安全》。
查看英文原文:Overcoming RESTlessness
總結
以上是生活随笔為你收集整理的持续演进,克服“REST缺乏”的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [模板] 长链剖分
- 下一篇: 自测题的整理(持续更新)