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