文章轉發自專業的Laravel開發者社區,原始連接: https://learnku.com/laravel/t...
這個話題在開發社區裏已經討論過一段時間,人們對此有不一樣的見解與觀點,那麼我應該使用哪個? 有不少東西須要成長但富有活力的新成員仍是經驗豐富的老成員? 在此以前讓咱們瞭解下 REST 和 GraphQL吧。laravel
REST即表述性狀態傳遞(英文:Representational State Transfer,簡稱REST),它符合特定的指南,是 Web API 實現的約束。是 Roy Fielding 博士在他的博士論文中提出來的一種軟件架構風格。它鼓勵客戶端和服務器以無狀態模式交換信息。 請記住,並不是全部 API 都是 REST,但全部 RESTful 服務都是 API。數據庫
GraphQL是Web API 的查詢語言。它由Facebook於2012年建立,並於2015年開源。它既不是架構模式,也不是Web服務。它是個中介,用來查詢從各類數據源接收的數據。 這些數據源能夠是數據庫或Web服務。瀏覽器
多年來,REST已成爲Web API的事實上的標準。 因爲它使用了標準的HTTP方法(GET,POST,PUT,DELETE等),隨着互聯網上的Web應用程序的增長,它也得以發展和普及。 此外,它的語言和平臺無關,使其成爲建立Web服務的更好選擇。 由於每一個數據都被視爲在調用URL時要發送的資源,因此甚至可使用Web瀏覽器或使用cURL請求來調用它。緩存
雖然REST很是成功,但因爲RESTful服務的規模和複雜性不斷增加,所以它的缺點變得很是明顯安全
在 RESTful 服務中一個 URL 表示一個資源。所以,當要獲取多個資源時你必須請求多個不一樣的 URL,進而帶來屢次數據交互。服務器
當咱們考慮一個博客應用。一篇博客下面有多條評論的情形。一般咱們要調用的 URL 以下數據結構
GET /posts/<postId> - 獲取特定的博客文章 GET /posts/<postId>/comments - 獲取上面博客文章關聯的全部評論 GET /posts/<postId>/comments/<commentId> - 獲取特定博客下的特定評論
你會發現咱們要請求的 URL 多了很多。這是由於實體 (這裏能夠理解爲博文和評論)之間的關聯關係更加複雜了。隨着應用變得愈來愈複雜,管理這些 API 也變得更加困難。架構
有時候,當您請求 API 接口時,您會得到沒必要要的數據和相關數據,有時候您沒法得到足夠的數據,因此您最終會進行屢次往返。 這是 RESTful 服務中的常見問題。 在某些狀況下,您可能只須要 2 - 3 個值,但您能夠得到大約 20 - 25 個值做爲響應。 這隻會經過增長響應時間,致使傳輸大量未使用的數據。 在後一種狀況下,您獲取的信息可能須要比從單個 URL 獲取的信息要多,所以有必要進行屢次往返。 這也致使客戶端獲取全部所需數據所花費的時間成本增長。微服務
API 版本控制是一種遵循的方法,以免使用響應格式的更改來破壞客戶端應用程序。 當 API 響應格式發生更改時,將建立新版本。 這樣作是爲了使生產客戶端應用程序能夠按預期運行,併爲開發人員提供一些休息的時間來遷移到新的 API 版本。工具
可是這個版本控制是一個問題,由於當新版本發佈時,它意味着新的 URL。 API 的維護和使用變得困難,而且常常致使重複的代碼。
並不是咱們從 RESTful 服務收到的全部數據都是強類型的,即它們沒有正確地給出特定數據。 這在記錄 API 時會成爲問題,由於咱們必須經過調用 URL 來指定客戶端能夠指望的數據類型。
在收到響應結構以前,客戶端不知道響應結構。因此,客戶端是被矇在鼓裏的。這可能常常致使一些錯誤和數據沒法正確處理,從而下降了消耗 API 的可靠性。
GraphQL 是由 Facebook 發明的,主要是爲了克服 REST 的缺點。
一個 GraphQL 服務只暴露一個端點以便客戶端能傳輸必要的查詢去檢索數據。 使用前面考慮過的相同示例,讓咱們看看 GraphQL 查詢
{ findPost(id: <postId>) { id title content author comments { id comment commentedBy } } }
正如你所看到的,咱們僅僅經過單個請求獲取到了全部必要的數據。 因此當你想要一個新字段你只須要將它添加進查詢中,它將在響應中呈現
GraphQL 被強類型模式所控制。這些類型既能夠是原始的也能夠是派生的。強類型系統容許 API 自文檔化,從而使客戶端知道在查詢特定查詢時會的到什麼響應。
GraphQL 提供了一種聲明式語法,以便客戶端精確地指定它們所需的字段。 這消除了因爲客戶端根據模式向 GraphQL 服務器聲明其數據需求而致使數據冗餘和不充分的可能性。
由於在 GraphQL 中一切都是模式(schema)驅動, 新增字段不會影響現存字段,並且 GraphQL 還爲廢棄字段提供 @deprecated
註釋,因此對 GraphQL 的擴展並非問題。 這就消除了 API 版本控制的須要。
這是 GraphQL 的一個很是棒的優勢。 API 服務器能夠經過相似 HTTP, HTTPS, WebSockets, TCP, UDP 等協議進行信息交換。 這是由於 GraphQL 甚少關心信息如何在客戶端與服務器之間進行交換。
哇,GraphQL 很棒,這是一個衆所周知的事實。可是世界上的任何東西都是有缺陷的,GraphQL 也沒法置身事外。
GraphQL 不支持瀏覽器和移動手機緩存,這一點區別於使用本地 HTTP 緩存機制的 RESTful 服務,所以咱們要爲實現 GraphQL 緩存付出額外努力。雖然有 Relay 這樣的工具提供了一些緩存支持,可是它們尚未 RESTful 服務使用的緩存機制成熟。
RESTful 服務利用 HTTP 狀態代碼來處理可能遇到的不一樣錯誤。對開發人員來講,這使得 APIs 的檢驗變得很是簡單和輕鬆。可是使用 GraphQL 服務老是返回 200 OK
響應。一個典型的 GraphQL 錯誤消息是這樣的,狀態碼爲 200 OK
。
{ errors: [ { message: 'Some error occurred' } ] }
這使得處理錯誤場景很是困難,而且使得檢驗過程很是麻煩。
和RESTful服務不一樣,GraphQL服務要求客戶端必須知道要查詢的數據模式。 若是您將API暴露給第三方,則基本上暴露了您的內部數據結構。 必須很是當心,由於客戶端不用很高的代價就能夠發起鏈接查詢,這可能會致使服務器上的拒絕服務(DoS)攻擊。
GraphQL社區仍然對如何處理GraphQL服務的安所有分感到困惑。仍然沒有集成身份驗證和受權的原生解決方案。它一般被抽象到業務邏輯層來受權用戶,可是咱們是否真的必須解析和驗證一個未經驗證的用戶的查詢仍然是GraphQL領域中的一個問題。
在RESTful服務中,很容易記錄執行的SQL查詢並進一步優化它。但在GraphQL的狀況下,解析性質是動態的,所以很難得到精確的查詢並進一步優化它。有時,字段解析器可能會致使N+1次查詢問題和複雜的鏈接操做。可是Facebook正在開發像DataLoader這樣的工具來解決這個確切的問題。因此,也許在將來,這不會是一個不利因素。
GraphQL在這個API生態系統中很是像一個嬰兒,這意味着隨時可能會出點問題以及破壞性更改,所以在使用與GraphQL相關的任何庫和模塊時,咱們必須很是細心。
首先我要說GraphQL只是一種工具,REST是一種架構模式。若是說用GraphQL取代REST,那就大錯特錯了。可是在這個微服務的時代,咱們將API分離並建立到原子級別,咱們能夠利用這兩個方面的優點,由於並無銀彈。
GraphQL服務將性能做爲首要任務,而RESTful服務則保持可靠性。
GraphQL節點能夠經過現有的RESTful服務做爲節點公開,好比/ graphql
,它能夠做爲運行GraphQL查詢的網關,同時也能夠爲某些場景維持REST節點。
在某些場景中, 使用 GraphQL 會更好, 也有一些場景中 REST 必然更好。所以在說哪個更好以前, 須要分析一下所涉及的需求和數據, 才知道哪一個更適合。