2018 GraphQL 漸進式導入的架構

GraphQL API Gateway with Schema Stitching

GraphQL 出來幾年熱度依然不減,從今年數場演講與文章中,看得出越來越成熟的趨勢,筆者有在 Side Project 先試用看看覺得挺不錯的,直到近期公司新專案總算開始準備導入 GraphQL,這篇文章主要整理了置底 Reference 段落列出的內容,來看看 GraphQL 可能有哪些架構方法,建議有時間可以自行詳讀一遍。

雖然說是新專案,仍然是建立在 Legacy System 之上,會使用到舊有的 REST API,因此需要分別從 Client Side 與 Server Side 的角度來探討,怎麼樣的架構適合漸進式的導入 GraphQL。

Client Side

REST vs. GraphQL moves data requirements to the client side. (Image credit, Image credit)

不免俗套先從 REST 的缺點來探討,現階段我們維運三年前開發的 MCS (MediaTek Cloud Sandbox) 中是全面採用 REST 的架構,要瀏覽 Detail 頁面至少打 7 支 Resource API,可以想像頁面的負擔相當大,在上圖 GraphQL 的設計理念中,透過將 Data Requirements 往前端搬移,讓頁面所需的資訊盡量能在一個 Request 內完成,來優化網路的傳輸問題。

Apollo Client 2.0

前端今年最熱門的狀態管理肯定非 Redux 莫屬,一旦要轉換為 GraphQL 的架構,可以挑選由 GraphQL 為出發點設計的 Relay 或 Apollo 框架,筆者比較偏好社群活躍度高的 Apollo Client 2.0,社群導向也相較有趣很多,另外 Apollo 背後用 Observable 實作相當不錯。


a. REST + GraphQL Hybrid

如果我們直接建立一個新的 GraphQL Server,會造成前端維護的困難,因為要同時處理 REST 與 GraphQL 的結構。為了提供彈性的調整空間,Apollo Client 2.0 抽象出的 Apollo Link 可以解決此類問題,其中 Apollo Link REST (apollo-link-rest or @n1ru4l/apollo-link-rest) 的擴充,讓你在定義 Schema 時可以使用 @rest Directive 整合額外用到的 REST API,而其背後會自動幫你轉換為 REST API 送出,Query 寫起來像是:

// example: GitHub
query userProfile {
person @rest(type: "Person", path: "people/1/") {
name
}
}

透過 Hybrid 的方式間接導入 GraphQL,頁面上新的功能用 GraphQL,部分也可以使用既有的 REST API,但是問題只解決了一半,還是會有上圖發出多個 Requests 的問題,官方套件也特別說明現階段還在開發中,尚未實作完 Mutation 的操作,所以暫時還不是一個很成熟的解法。

b. GraphQL Layer

我們也可以把 GraphQL Server 抽出來放到中間當作 GraphQL Layer,除了可以用來封裝背後任何既有 API Service 外,新的功能也能直接與 Database 溝通,並且將邏輯實作在這台 GraphQL Server 上,最後只提供一個 GraphQL Endpoint 給前端使用。

c. GraphQL API Gateway

API Gateway delegate to GraphQL Native
New features will be built in a GraphQL Native way, and combined into the existing GraphQL API using schema stitching. — GraphQL API Gateway & GraphQL Native

筆者認為這是目前看到算是 Best Practice 的架構,中間多了一層 API Gateway 的設計,這台 GraphQL Gateway 不直接與 Database 溝通,而是把前端的 Requests 需求往後面的 API Service 送。而後面直接與 Database 串接的 GraphQL Server 稱為 GraphQL Native。

Schema Stitching & Delegate

後面的 API Service 不論你要用 REST 實作,又或是直接使用 GraphQL 更好,能透過 Introspection Query 把 GraphQL Native 定義的 Schema 存放到 Gateway 機器上,一旦 API Gateway 收到 Request 就 Delegate 到 GraphQL Native Service 去,甚至是可以透過 Schema Stitching 的設定,將多個 GraphQL Microservice 合併成一個。

Caching & Error Tracing

API Gateway 除了可以保有現有的架構外,可以在這個層級處理棘手的 Caching 以及 Tracing 問題,因此 Apollo 也提供 Engine 服務來幫你做掉這塊,詳情可以參考:


Conclusion

這篇文章簡單整理了幾種可能的架構方法,新專案還沒有正式的啟動,算是 2018 的新年許願,希望能夠正式導入 GraphQL,也透過這次的 Survey 看到不同的設計理念。最後一個 Gateway 架構雖然是相較最彈性的,但也伴隨系統的複雜化,最後會評估團隊人力狀況做出不同的決定,如果對後續筆者專案採用的架構有興趣,歡迎關注並訂閱 Medium 喔!

Further Readings

  1. GraphQL Microservice with Apollo — 使用 GraphQL 獲取 Medium 最新文章列表

References

  1. How do GraphQL remote schemas work? — Understanding GraphQL schema stitching (Part I)
  2. GraphQL Schema Stitching explained: Schema Delegation — Understanding GraphQL schema stitching (Part II)
  3. Apollographql Docs
  4. GraphQL schema stitching / GitHub
  5. The GraphQL stack: How everything fits together
  6. GraphQL vs. REST
  7. How to GraphQL? — Big Picture (Architecture)