GraphQL,API的新工具規(guī)范
譯文【51CTO.com快譯】GraphQL服務(wù)端向客戶端提供了一種預(yù)定義式的架構(gòu)。它支持從服務(wù)端檢索某種模型的數(shù)據(jù)。其結(jié)構(gòu)模式充當(dāng)了服務(wù)端和客戶端之間的連接器,同時(shí)也定義了訪問信息的過程。
GraphQL架構(gòu)的各種基本元素,都是以SDL(Schema Definition Language,模式定義語言)記錄下來的。這些記錄解釋了哪些對象可以在特定的服務(wù)端被請求,它們擁有哪些字段,允許請求獲取哪些類型的數(shù)據(jù),以及這些類型之間的關(guān)系。
為了確保服務(wù)端能夠響應(yīng)某種查詢,并保證客戶端可以根據(jù)既定的模式來驗(yàn)證該查詢,您可以開發(fā)出特有的GraphQL模式,并使用任何一種編程語言來創(chuàng)建對應(yīng)的接口。籍此,您便可以根據(jù)與結(jié)果相匹配的GraphQL查詢格式,來預(yù)測對應(yīng)的結(jié)果。此外,GraphQL模式還能夠避免出現(xiàn)諸如結(jié)構(gòu)錯(cuò)誤或數(shù)據(jù)不可用,等異常情況。
可見,只有在GraphQL的相關(guān)操作到達(dá)后端應(yīng)用之后,針對完整架構(gòu)的解析才能進(jìn)行,而前端應(yīng)用的數(shù)據(jù)也才能被準(zhǔn)確地解析出來。
GraphQL操作
目前,GraphQL具有如下三種主要操作方式:
- 查詢讀取數(shù)據(jù)
- 寫入數(shù)據(jù)的變化
- 隨著時(shí)間的推移,自動(dòng)接收實(shí)時(shí)數(shù)據(jù)
GraphQL將全量數(shù)據(jù)集的方式改進(jìn)為:僅在同一個(gè)請求中就實(shí)現(xiàn)數(shù)據(jù)的查詢與接受。這種客戶端驅(qū)動(dòng)式(client-driven)的方法備受開發(fā)人員的推崇。至于返回的數(shù)據(jù)類型,GraphQL將此類數(shù)據(jù)控制權(quán)交付給了客戶端。
而對于REST而言,由于服務(wù)端預(yù)先定義好了所有資源的可用數(shù)據(jù)。因此就算只需要一部分?jǐn)?shù)據(jù),客戶端也必須通過重復(fù)的網(wǎng)絡(luò)請求,來獲取資源中的全量信息。這就產(chǎn)生了所謂的過度獲取(over-fetching)的問題。
GraphQL與REST的優(yōu)勢相比
GraphQL和REST都是構(gòu)建和使用API所需的規(guī)范。這兩種技術(shù)的共同特點(diǎn)是:在通過發(fā)送查詢請求來檢索資源時(shí),它們都可以在請求中返回JSON數(shù)據(jù)。
此外,它們都可以通過HTTP的方式進(jìn)行操作。而由于它們都充當(dāng)了調(diào)用服務(wù)端函數(shù)的數(shù)據(jù)入口,因此REST和GraphQL的端點(diǎn)字段有著許多相似之處。
雖然有著上述共同點(diǎn),但是它們的概念模型卻有著明顯的差異。GraphQL建立在圖形基礎(chǔ)上的;而REST則建立在文件之上。這就導(dǎo)致了開發(fā)人員在構(gòu)建和使用API上會(huì)產(chǎn)生不同的體驗(yàn)。
就運(yùn)行速度而言,GrapgQL更快。用戶可以通過選擇需要在其上運(yùn)行的查詢字段數(shù)量,來減少請求以及實(shí)際消耗的時(shí)間。這便是GraphQL API比REST API更受歡迎的原因之一。此外還有:
1)是多面(Multifaceted)系統(tǒng)和微服務(wù)的絕配
GraphQL可以通過在API后端集成多個(gè)系統(tǒng),來統(tǒng)一和隱藏實(shí)現(xiàn)的復(fù)雜性。GraphQL的服務(wù)端負(fù)責(zé)從當(dāng)前的系統(tǒng)中獲取數(shù)據(jù),然后將其打包成為GraphQL的響應(yīng)格式。這對于多年來一直需要通過大量擴(kuò)展第三方API的舊版架構(gòu)來說,是尤為重要的。同時(shí),GraphQL也減少了不少的維護(hù)負(fù)擔(dān)。
通過將單體的后端應(yīng)用遷移到微服務(wù)的架構(gòu)之中,我們可以把多個(gè)微服務(wù)合并到GraphQL的模式里,以實(shí)現(xiàn)它們之間的通信。此外,即使每一個(gè)微服務(wù)都定義了自己的GraphQL模式,并具有自己的GraphQL端點(diǎn),我們也可以通過某一個(gè)GraphQL API網(wǎng)關(guān),來將其整合為全局模式。
2)通過單個(gè)API的調(diào)用來獲取信息
由于REST分散在各個(gè)端點(diǎn)處,因此開發(fā)人員往往需要合并多個(gè)端點(diǎn),來收集所有需要的數(shù)據(jù)。而對于專注于主要任務(wù)的GraphQL而言,開發(fā)人員僅需一個(gè)API調(diào)用,便可以請求到各種所需的信息。
3)恰當(dāng)獲取數(shù)據(jù)
以REST方式獲取響應(yīng)數(shù)據(jù)有一個(gè)不穩(wěn)定的因素:數(shù)據(jù)要么太少要么過多,因此,開發(fā)人員不得不執(zhí)行多個(gè)查詢請求。而由于GraphQL能夠通過單個(gè)請求,獲取確切的數(shù)據(jù),因此它有效地解決了此類問題。
4)按需調(diào)整請求
通常,開發(fā)人員只能通過REST API文檔,來請求特定端點(diǎn)的相關(guān)功能與參數(shù)。而GraphQL能夠描述數(shù)據(jù)的類型、字段以及它們之間的交互點(diǎn)。因此GraphQL開發(fā)人員可以自定義請求,并訪問各種必要的信息。
5)開箱即用的身份驗(yàn)證和類型檢查
GraphQL的自省(introspection)功能使得用戶可以檢測類型、并查找模式,進(jìn)而確保應(yīng)用程序只采用正確的結(jié)構(gòu),去請求所需的內(nèi)容。
此外,開發(fā)人員還可以借助GraphQL IDE,將新的字段添加到當(dāng)前的查詢之中,而無需額外地驗(yàn)證數(shù)據(jù)格式。他們需要做的只是編寫解析器。
6)自動(dòng)生成API文檔
由于文檔與代碼緊密相關(guān),因此GraphQL API的變更能夠保持同步。一旦有某個(gè)字段、查詢或類型發(fā)生了改變,其對應(yīng)的文檔將自動(dòng)觸發(fā)修改。
7)API的迭代不產(chǎn)生新版本
作為一款不斷迭代的API,REST提供了多個(gè)不同的API版本。這就意味著:開發(fā)人員必須保留舊的版本,直至遷移到新的版本上。
而GraphQL則可以從架構(gòu)中直接刪除“老化”的字段,而不會(huì)影響到將來對于現(xiàn)有方式的查詢。此舉確保了GraphQL在不斷迭代的過程中,仍然可以不間斷地訪問到目標(biāo)應(yīng)用的新功能,同時(shí)也能夠保持服務(wù)端代碼的整潔與易維護(hù)性。
8)代碼共享
如果需要代碼重用,那些在GraphQL多個(gè)查詢中所用到的字段,可以實(shí)現(xiàn)高級別的組件共享。這些代碼段可以讓用戶在保持相同的架構(gòu)字段的基礎(chǔ)上,訪問到各種類型的數(shù)據(jù)。
9)詳細(xì)的錯(cuò)誤消息
為了能夠準(zhǔn)確地定位到程序中出現(xiàn)的問題,以及對應(yīng)的解決方案,REST需要通過檢查HTTP頭,來獲取響應(yīng)狀態(tài)。而在GraphQL中,如果處理過程發(fā)生了錯(cuò)誤,則后端會(huì)提供包含有解析程序的詳細(xì)消息,以準(zhǔn)確定位查詢失敗的確切部分。
10)權(quán)限
相較于REST的簡單視圖,開發(fā)人員可以在創(chuàng)建GraphQL模式時(shí),選擇需要全面展示的功能,及其具體的工作方式。因此,用戶能夠根據(jù)具體情況,細(xì)粒度地顯示不同程度的視圖。
總結(jié)
我們不能武斷地認(rèn)為:作為工具的GraphQL將可以完全替代作為架構(gòu)模式的REST。到底哪一個(gè)更合適您手頭的項(xiàng)目,還是取決于特定的API交互模式,以及具體的使用場景。
原文標(biāo)題:GraphQL: The Future of APIs,作者:Noa James
【51CTO譯稿,合作站點(diǎn)轉(zhuǎn)載請注明原文譯者和出處為51CTO.com】