GraphQL 技術棧揭祕

本文整理自2017年 GraphQL 峯會上的演講,詳述緩存、追蹤、模式拼接和 GraphQL 將來發展等有關話題。

Facebook 開源 GraphQL 至今已兩年有餘。兩年來,社區成倍增加,成千上萬的公司在產品中使用 GraphQL。在今年10月份舉辦的 GraphQL 峯會上,我有幸在次日發表開幕主題演講。讀者能夠在 YouTube 上觀看完整的演講,或閱讀本文瀏覽概要。html

首先,我將介紹一下 GraphQL 的現狀,而後討論在不久的未來如何發揚它的主要優點。具體來講,咱們將介紹三個完整的 GraphQL 集成示例:緩存,性能追蹤和模式拼接。讓咱們開始吧!前端


GraphQL 的特別之處?

有三個主要因素使得 GraphQL 從其餘 API 技術中脫穎而出:java

  1. GraphQL 擁有明確的查詢語言,這是描述數據需求的好方法,還有定義良好的模式,可以暴露 API 能力。它是惟一可以指定方程兩側(譯者注:視圖和模型)的主流技術,它的全部優點都源於這兩個概念的相互做用。
  2. GraphQL 可以幫你將 API 提供者與消費者解耦。在像 REST 這樣基於端點的 API 中,返回數據的結構由服務器決定。在 GraphQL 中,響應的結構與使用它的 UI 代碼保持關聯,這樣會更加天然,使得你能夠專一於關注業務而不是技術
  3. 因爲 GraphQL 查詢會被附加到使用它的代碼上,所以能夠將該查詢視爲數據獲取單元。GraphQL 可以預先知道 UI 組件的全部數據需求,從而啓用新的服務器功能。例如,在單個查詢中對底層 API 調用進行批處理和緩存,表明了 UI 中某一部分所需的數據,使用 GraphQL 將會令其很是簡單。

關注業務,而不是技術:GraphQL 將數據需求放在它們所屬的客戶端。git

如今,咱們來看看人們對於數據請求常常關注的三個方面,以及 GraphQL 如何利用上面提到的屬性進行全方位改進。github

請注意,雖然下面討論的許多功能是你如今就可以使用的,但其中一部分仍屬於將來的願景。若是你和我同樣對這件事感到興奮,那麼請滾動到底部參與其中。數據庫

1. 交叉請求緩存

人們常常問的第一件事情就是——我怎麼用個人 GraphQL API 作交叉請求緩存?將常規 HTTP 緩存應用於 GraphQL 時會出現這樣一些問題:後端

  • HTTP 緩存一般不支持 POST 請求或長緩存鍵
  • 越複雜的請求可能意味着更少的緩存命中
  • GraphQL 的傳輸是獨立的,所以 HTTP 緩存並不老是可行

可是,GraphQL 也帶來了許多新的可能性:緩存

  • 訪問後端時,在模式和解析器旁聲明緩存控制信息的可能性
  • 基於模式的自動化細粒度緩存控制,而沒必要單獨考慮每一個請求

咱們應該如何使用 GraphQL 來生效緩存,以及如何利用好這些新的可能性呢?ruby

究竟應該在哪裏執行緩存?

首先,咱們得肯定緩存功能應該設計在哪。一開始的直覺多是緩存邏輯應該放在 GraphQL 服務器自己內。然而,像 DataLoader 這樣簡單的工具在同時執行多個 GraphQL 請求時並不能很好地工做,而將緩存功能放在咱們的服務器代碼中會使實現變得很是複雜。所以咱們應該把它放在別的地方。服務器

事實證實,就像在 REST 中同樣,在 API 層的兩端都進行緩存是有意義的:

  1. 在位於基礎設施層中的 GraphQL API 以外緩存整個響應。
  2. 緩存 GraphQL 服務器底層對數據庫和微服務的請求。

對於第二點,須要你現有的緩存基礎設施工做良好。對於第一點,咱們須要一個位於 API 以外的層,而且可以以 GraphQL 的方式執行緩存等操做。本質上講,這種架構可以將複雜度從 GraphQL 服務器中分離出來:

將複雜度轉移到位於客戶端和服務器之間新的分層。

我將這個組件稱之爲 GraphQL 網關。在 Apollo 團隊內部,咱們認爲這個新的網關層很是重要,每一個人都須要將其做爲 GraphQL 基礎架構的一部分。

這就是爲何在今年的 GraphQL 峯會期間,咱們推出了首個 GraphQL 網關 Apollo Engine

用於緩存控制的 GraphQL 響應擴展

正如我在開始時提到的那樣,GraphQL 的一大優勢是其擁有巨大的工具生態系統,全部工具都圍繞着 GraphQL 的查詢和模式來工做。我認爲像緩存這樣的功能也應該以一樣的方式工做。這就是爲何咱們要介紹 Apollo 緩存控制,它使用了 GraphQL 規範中內置的一個名爲 擴展 的特性,將緩存控制信息包含在響應中。

使用咱們的 JavaScript 參考實現,能夠很容易在你的 schema 中添加緩存控制標識:

使用 apollo-cache-control-js 的緩存控制標識

這個新的緩存控制規範創建在 GraphQL 的主要優點上,我對此感到很是興奮。它使你可以細粒度地指定相關數據的信息,並利用 GraphQL 執行將相關的緩存控制標識發回給調用者,並且這與語言和傳輸方式無關。

自從我在 GraphQL Summit 上發表這個演講後,Oleg Ilyenko 已經發布了 Sangria 的緩存控制工做版本,由他維護的 Scala GraphQL 實現。

使用網關緩存

如今咱們能夠在 GraphQL 服務器中返回緩存控制標識,因此咱們有一個明確的方法來在網關中進行緩存。技術棧中的每一部分都起着做用:

技術棧中全部部分之間的協做能夠藉助緩存來完成。

須要注意的一件很酷的事情是,大多數人已經在他們的 GraphQL 棧中擁有了一個緩存:好比 Apollo Client 和 Relay 這樣的庫在前端緩存你的數據。在 Apollo 客戶端的將來版本中,來自響應的緩存控制信息將被用於自動在前端過時舊數據。因此,就像 GraphQL 的其餘部分同樣,服務器描述它的功能,客戶端指定它的數據需求,而後一切工做配合正常。

如今,咱們來看看另外一個貫穿整個技術棧的 GraphQL 功能的例子。

2. 追蹤

藉助 GraphQL,前端開發人員可以以相較基於端點的系統更精細的方式處理數據。他們能夠確切地請求他們須要的數據,並跳過他們不打算使用的字段。受益於此,咱們能夠展現詳細的性能信息,並之前所未有的方式使其具備可操做性。

不要知足於不透明的總查詢時間—— GraphQL 使你可以獲曉字段級別的詳細耗時。

你能夠認爲 GraphQL 是首個內置細粒度查看的 API 技術。這不是藉助某個特定的工具—— GraphQL 第一次合理地讓前端開發人員可以得到逐個字段的執行時間,而後調整他們的查詢來解決問題。

跨棧追蹤

事實證實,追蹤跟緩存同樣,對於整個棧的協做大有裨益。

每一部分在提供追蹤數據和使其具備可操做性方面發揮着做用。

服務器可以提供相關信息做爲響應結果的一部分,就像提供緩存標識同樣,網關能夠提取和聚合這些信息。重申,使用網關組件來處理複雜的功能,而不是在服務器進程中處理。

在這種狀況下,客戶端的主要功能是將查詢與 UI 組件鏈接起來。這很是關鍵,所以你能夠將 API 層的性能與其對前端的影響聯繫起來。這將是首次,你能夠直接將後端請求的性能與其在頁面上受影響的 UI 組件關聯起來。

GraphQL 追蹤擴展

就像緩存同樣,經過利用 GraphQL 的響應擴展功能,可以以服務器無關的方式實現上述功能。Apollo Tracing 規範已經在 NodeRubyScalaJavaElixir 上實現了,其定義了一種 GraphQL 服務器以標準方式爲解析器返回耗時數據的方式,可以被任何工具所使用。

想象一下,你全部的 GraphQL 工具均可以訪問性能數據:

共享抽象容許工具使用諸如追蹤數據等信息。

藉助 Apollo Tracing,你能夠在 GraphiQL,編輯器或其餘任何地方獲取性能數據。

目前爲止,咱們一直在談論單個客戶端和單個服務器之間的交互。咱們的最後一個例子,一塊兒來看看咱們如何經過 GraphQL 來模塊化咱們的架構。

3. 模式拼接

GraphQL 最好的地方就是能夠在一個地方訪問全部的數據。可是,這樣作的代價是:你須要將整個 GraphQL 模式做爲單個代碼庫來實現,以便可以在一個請求中查詢它。 若是你擁有一個模塊化的架構,而該架構同時具備單個統一 GraphQL API 的好處呢?

模式拼接的概念很簡單:GraphQL 能夠很容易地將多個 API 合併爲一個,所以你能夠將模式的不一樣部分實現爲獨立的服務。這些服務能夠分開部署,用不一樣的語言編寫,甚至能夠由不一樣的組織維護。

這有一個例子

在單個查詢中結合來自 GraphQL 峯會的票務系統和天氣 API 的數據:
https://launchpad.graphql.com/130rr3r49

在上面的截圖中,你能夠看到對於一個拼接 API 的單個查詢是如何將提供不一樣服務的兩個獨立查詢合併在一塊兒,這種方式對客戶端來講是徹底不可見的。經過這種方式,你能夠像使用樂高積木般合併多個 GraphQL 模式。

咱們實現了一個能用的版本,放到了 Apollo graphql-tools 庫裏,你能夠如今去試用。具體查看文檔。

在網關中拼接

模式拼接的概念在整個棧中也能夠很好地工做。咱們認爲新的網關層長期來看會是一個執行拼接操做的好地方,你可使用任何你想要的技術構建你的模式,如 Node.jsGraphcoolNeo4j

事實證實,模式拼接與 GraphQL 棧的每一部分都息息相關。

客戶端也能夠加入進來!就像你使用一個查詢從多個後端加載數據同樣,你也能夠在客戶端上組合數據源。最近發佈的 Apollo Client 2.0 中的新客戶端狀態管理功能使你能夠在單個查詢中獲取來自於客戶端狀態和任意數量後端的數據。

結論

但願你經過閱讀這篇文章或者看完演講後能知道一件事情,那就是儘管現今的 GraphQL 工具已經很棒了,將來還有更多的潛力。咱們只是抓住了 GraphQL 提供的抽象和功能的表面。

我想以上述提到的概念的待辦事項清單來結束本篇文章:

整合這些新功能還有不少工做要作,特別是在開發者工具和編輯器方面。

要發掘 GraphQL 的所有潛力,還有不少事情要作。在 Apollo 團隊,咱們正在盡咱們所能來作這件事情,但單獨的一我的,團隊或組織不可能獨自完成這個目標。爲了實現將來的願景,咱們須要共同合做,共同構建出全部這些解決方案。

不管咱們在哪裏,有一點是明確的:GraphQL 已經成千上萬的公司的變革技術,而這只是一個開始! 我火燒眉毛地想知道在接下來的兩年,五年和十年中編寫應用程序會是什麼樣子,由於這將是難以想象的。

參與其中

若是你像 Apollo 同樣對 GraphQL 的潛力感興趣,請考慮加入咱們的社區。咱們已經組建了一個幫助頁面 來幫助你入門。

GraphQL 峯會上的其餘會議即將發佈!在Twitter上關注 @graphqlsummit 或訂閱 Apollo 的 Youtube 頻道 以獲取最新內容。

終於寫完了……

相關文章
相關標籤/搜索