GraphQL是什麼“渣渣“?它想幹掉RESTful

GraphQL簡介

  • GraphQL是一種新的API標準,它提供了一種比REST更有效、更強大和更靈活的替代方案。

  • 它是由Facebook開發並開源的,現在由來自世界各地的公司和個人組成的大型社區維護。

  • GraphQL本質上是一種基於api的查詢語言,現在大多數應用程序都需要從服務器中獲取數據,這些數據存儲可能存儲在數據庫中,API的職責是提供與應用程序需求相匹配的存儲數據的接口。

  • 它是數據庫無關的,而且可以在使用API的任何環境中有效使用,我們可以理解爲GraphQL是基於API之上的一層封裝,目的是爲了更好,更靈活的適用於業務的需求變化。

簡單的來說,它

它的工作模式是這樣子的:

GraphQL 對比 REST API 有什麼好處?

REST API 的接口靈活性差、接口操作流程繁瑣,GraphQL 的聲明式數據獲取,使得接口數據精確返回,數據查詢流程簡潔,照顧了客戶端的靈活性。

客戶端拓展功能時要不斷編寫新接口(依賴於服務端),GraphQL 中一個服務僅暴露一個 GraphQL 層,消除了服務器對數據格式的硬性規定,客戶端按需請求數據,可進行單獨維護和改進。

REST API 基於HTTP協議,不能靈活選擇網絡協議,而傳輸層無關、數據庫技術無關使得 GraphQL 有更加靈活的技術棧選擇,能夠實現在網絡協議層面優化應用。

舉個經典的例子:前端向後端請求一個book對象的數據及其作者信息。我用動圖來分別演示下REST和GraphQL是怎麼樣的一個過程。先看REST API的做法:

REST API獲取數據

再來看GraphQL是怎麼做的:

GraphQL獲取數據

可以看出其中的區別:

與REST多個endpoint不同,每一個的 GraphQL 服務其實對外只提供了一個用於調用內部接口的端點,所有的請求都訪問這個暴露出來的唯一端點。

Endpoints對比

REST API's Endpoints

GraphQL 實際上將多個 HTTP 請求聚合成了一個請求,將多個 restful 請求的資源變成了一個從根資源 POST 訪問其他資源的 Comment 和 Author 的圖,多個請求變成了一個請求的不同字段,從原有的分散式請求變成了集中式的請求,因此GraphQL又可以被看成是圖數據庫的形式。

圖數據庫模式的數據查詢

那我們已經能看到GraphQL的先進性,接下來看看它是怎麼做的。

GraphQL 思考模式

使用GraphQL接口設計獲取數據需要三步:

GraphQL獲取數據三步驟

1、首先要設計數據模型,用來描述數據對象,它的作用可以看做是VO,用於告知GraphQL如何來描述定義的數據,爲下一步查詢返回做準備;

2、前端使用模式查詢語言(Schema)來描述需要請求的數據對象類型和具體需要的字段(稱之爲聲明式數據獲取);

3、後端GraphQL通過前端傳過來的請求,根據需要,自動組裝數據字段,返回給前端。

GraphQL的這種思考模式是不是完美解決了之前遇到的問題呢?先總結它的好處:

在它的設計思想中,GraphQL 以圖的形式將整個 Web 服務中的資源展示出來,客戶端可以按照其需求自行調用,類似添加字段的需求其實就不再需要後端多次修改了。

創建GraphQL服務器的最終目標是:允許查詢通過圖和節點的形式去獲取數據。

GraphQL執行邏輯

有人會問:

  • 使用了GraphQL就要完全拋棄REST了嗎?

  • GraphQL需要直接對接數據庫嗎?

  • 使用GraphQL需要對現有的後端服務進行大刀闊斧的修改嗎?

答案是:NO!不需要!

它完全可以以一種不侵入的方式來部署,將它作爲前後端的中間服務,也就是,現在開始逐漸流行的 前端 —— 中端 —— 後端 的三層結構模式來部署!

那就來看一下這樣的部署模式圖:

也就是說,完全可以搭建一個GraphQL服務器,專門來處理前端請求,並處理後端服務獲取的數據,重新進行組裝、篩選、過濾,將完美符合前端需要的數據返回。

新的開發需求可以直接就使用GraphQL服務來獲取數據了,以前已經上線的功能無需改動,還是使用原有請求調用REST接口的方式,最低程度的降低更換GraphQL帶來的技術成本問題!

如果沒有那麼多成本來支撐改造,那麼就不需要改造!

只有當原有需求發生變化,需要對原功能進行修改時,就可以換成GraphQL了。

GraphQL應用的基本架構

下圖是一個 GraphQL 應用的基本架構,其中客戶端只和 GraphQL 層進行 API 交互,而 GraphQL 層再往後接入各種數據源。這樣一來,只要是數據源有的數據, GraphQL 層都可以讓客戶端按需獲取,不必專門再去定接口了。

一個GraphQL服務僅暴露一個 GraphQL Endpoint,可以按照業務來進行區分,部署多個GraphQL服務,分管不同的業務數據,這樣就可以避免單服務器壓力過大的問題了。

GraphQL特點總結

  • 聲明式數據獲取(可以對API進行查詢): 聲明式的數據查詢帶來了接口的精確返回,服務器會按數據查詢的格式返回同樣結構的 JSON 數據、真正照顧了客戶端的靈活性。

  • 一個微服務僅暴露一個 GraphQL 層:一個微服務只需暴露一個GraphQL endpoint,客戶端請求相應數據只通過該端點按需獲取,不需要再額外定義其他接口。

  • 傳輸層無關、數據庫技術無關:帶來了更靈活的技術棧選擇,比如我們可以選擇對移動設備友好的協議,將網絡傳輸數據量最小化,實現在網絡協議層面優化應用。

Part 2 Schema & Type

GraphQL支持的數據操作

GraphQL對數據支持的操作有:

  • 查詢(Query):獲取數據的基本查詢。

  • 變更(Mutation):支持對數據的增刪改等操作。

  • 訂閱(Subscription):用於監聽數據變動、並靠websocket等協議推送變動的消息給對方。

GraphQL的核心概念:圖表模式(Schema)

要想要設計GraphQL的數據模型,用來描述你的業務數據,那麼就必須要有一套Schema語法來做支撐。

想要描述數據,就必須離不開數據類型的定義。所以GraphQL設計了一套Schema模式(可以理解爲語法),其中最重要的就是數據類型的定義和支持。

那麼類型(Type)就是模式(Schema)最核心的東西了。

什麼是類型?

  • 對於數據模型的抽象是通過類型(Type)來描述的,每一個類型有若干字段(Field)組成,每個字段又分別指向某個類型(Type)。這很像Java、C#中的類(Class)。

  • GraphQL的Type簡單可以分爲兩種,一種叫做Scalar Type(標量類型),另一種叫做Object Type(對象類型)。

那麼就分別來介紹下兩種類型。

標量類型(Scalar Type)

標量是GraphQL類型系統中最小的顆粒。類似於Java、C#中的基本類型。

其中內建標量主要有:

  • String

  • Int

  • Float

  • Boolean

  • Enum

  • ID

上面的類型僅僅是GraphQL默認內置的類型,當然,爲了保證最大的靈活性,GraphQL還可以很靈活的自行創建標量類型。

對象類型(Object Type)

僅有標量類型是不能滿足複雜抽象數據模型的需要,這時候我們可以使用對象類型。

通過對象模型來構建GraphQL中關於一個數據模型的形狀,同時還可以聲明各個模型之間的內在關聯(一對多、一對一或多對多)。

對象類型的定義可以參考下圖:

對象模型引入關聯關係

是不是很方便呢?我們可以像設計類圖一樣來設計GraphQL的對象模型。

類型修飾符(Type Modifier)

那麼,類型系統僅僅只有類型定義是不夠的,我們還需要對類型進行更廣泛性的描述。

類型修飾符就是用來修飾類型,以達到額外的數據類型要求控制。

比如:

  • 列表:[Type]

  • 非空:Type!

  • 列表非空:[Type]!

  • 非空列表,列表內容類型非空:[Type!]!

在描述數據模型(模式Schema)時,就可以對字段施加限制條件。

例如定義了一個名爲User的對象類型,並對其字段進行定義和施加限制條件:

那麼,返回數據時,像下面這種情況就是不允許的:

Graphql會根據Schema Type來自動返回正確的數據:

其他類型

除了上面的,Graphql還有一些其他類型來更好的引入面向對象的設計思想:

接口類型(Interfaces):其他對象類型實現接口必須包含接口所有的字段,並具有相同的類型修飾符,纔算實現接口。

比如定義了一個接口類型:

那麼就可以實現該接口:

聯合類型(Union Types):聯合類型和接口十分相似,但是它並不指定類型之間的任何共同字段。幾個對象類型共用一個聯合類型。

輸入類型(Input Types):更新數據時有用,與常規對象只有關鍵字修飾不一樣,常規對象時 type 修飾,輸入類型是 input 修飾。

比如定義了一個輸入類型:

前端發送變更請求時就可以使用(通過參數來指定輸入的類型):

所以,這樣面向對象的設計方式,真的對後端開發人員特別友好!而且前端MVVM框架流行以來,面向對象的設計思想也越來越流行,前端使用Graphql也會得心應手。

Graphql 技術接入架構

那麼,該怎麼設計來接入我們現有的系統中呢?

將Graphql服務直連數據庫的方式:最簡潔的配置,直接操作數據庫能減少中間環節的性能消耗。

集成現有服務的GraphQL層:這種配置適合於舊服務的改造,尤其是在涉及第三方服務時、依然可以通過原有接口進行交互。

直連數據庫和集成服務的混合模式:前兩種方式的混合。

可以說是非常靈活了!你都不用擔心會給你帶來任何的麻煩。

服務端實現

在服務端, GraphQL 服務器可用任何可構建 Web 服務器的語言實現。有以下語言的實現供參考:

C# / .NET、Clojure、Elixir、Erlang、Go、Groovy、Java、JavaScript、Julia、Kotlin、Perl、PHP、Python、R、Ruby、Rust、Scala、Swift... 種類繁多,幾乎流行的語言都有支持。

客戶端實現

在客戶端,Graphql Client目前有下面的語言支持:C# / .NET、Clojurescript、Elm、Flutter、Go、Java / Android、JavaScript、Julia、Swift / Objective-C、iOS、Python、R。覆蓋了衆多客戶端設計語言,而其他語言的支持也在推進中。

來源 | http://suo.im/5W1XNE

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章