- 原文地址:GRAPHQL: A RETROSPECTIVE
- 原文做者:Rob Kirberich
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:EmilyQiRabbit
- 校對者:Eternaldeath
在 2016 年底,咱們決定用 Python 和 React 重寫老舊的 PHP 遺留系統。因爲只有四個月的時間在 2017 年的節日(到來前)及時創建 MVP(模式開發的系統),咱們必須很是謹慎地決定如何投入時間。前端
咱們投入使用的技術之一就是 GraphQL。咱們中以前還歷來沒有人用過它,但咱們認爲它對於快速交付以及能讓人們獨立工做相當重要。python
事實證實這是一個很是好的決定,因此兩年後咱們想回顧並分享從那時起學到的東西...react
咱們從遺留系統學到的教訓,大大影響了咱們,因而咱們決定使用 GraphQL。咱們在至關數量的微服務之間使用 REST APIS,致使不少混亂,如不兼容的接口,不一樣的資源標識符和很是複雜的部署。任何 API 的變更都須要同時部署全部使用了這個 API 的服務以免停機故障,這會常常出現錯誤並致使很長的發佈週期。在單個 API 網關使用 GraphQL,咱們將能夠大大簡化服務格局。咱們也決定了使用 Relay,它爲咱們提供了一種識別資源的單一的、全局的方式,以及組織 GraphQL 模型的簡單方法。android
咱們使用單一服務做爲 GraphQL 服務器,它反過來會請求各類後端服務 -- 其中大部分是 REST APIs,可是由於它們都只和網關通訊,因此它們可使用任何想用的接口。網關被設計爲徹底無狀態的,這對於可擴展性大有裨益。緩存也是在 GraphQL 網關中,所以,只需擴大網關實例的數量,就能夠輕鬆擴展整個系統。ios
API 網關並非 GraphQL 世界的規章,因此爲何儘管使用它們意味着須要從網關到後臺服務的附加請求,咱們還要使用呢?對於咱們而言,最大的緣由就是減小 API 的相互依賴。沒有網關的話,咱們的服務結構將會差很少像這樣:git
不少服務都和不少其餘服務互通,致使須要大量的 API 鏈接,鏈接數量會以大體至關於服務數量的二次方的速度增加。這不但幾乎不可能讓任何人記住,同時還在處理中斷,維護和 API 更改時,增長了大量複雜性。github
即便在這樣的網絡中,GraphQL 也可以幫助提高向後兼容性,但這是當你在服務之間放置一個單一網關的時候所會發生的事情:web
突然間,就僅有線性數量的鏈接了,每一個新的服務僅會在網絡圖中增長一個新鏈接。API 變化僅須要影響它的源服務和網關。數據庫
API 網關是服務互相通訊的惟一途徑,這就大大下降了複雜度。它還爲緩存,縮放,監視和分析建立了一個很好的中心位置。通常來講,只有一項服務負責這麼多事情並非一個好主意 -- 而是一個故障點。django
可是,API 網關是無狀態的。它沒有數據庫,沒有本地資源也沒有認證。這意味着它能夠在水平方向上縮放自如,同時由於它還負責了緩存,因此僅增長網關實例的數量就有助於顯著解決流量高峯(的問題)。
固然,網關也不是全無代價的:一個請求如今要發送兩次了,而且若是一個後臺服務想要和另外一個後臺服務通訊,就必須經過網關。這對於建立一個更易於維護的中心接口很是有用,可是對於性能來講並非很好。這就是無狀態網關展示本身光輝的時候。由於網關代碼在哪裏運行並不重要,那就沒有什麼能阻止咱們將每一個後端服務都做爲其本身的網關。咱們將 GraphQL 接口移動到了每一個服務中,直接發送網絡請求,而不是發送兩次,這樣徹底不須要使用 GraphQL 服務器,可是卻依舊保留了全部 GraphQL 中心模型的優點。而且因爲咱們使用了 Python 定義了 GraphQL 模型,咱們決定更深一步,經過從 GraphQL 模型中自動生成 API 包裝器,能夠直接在 Python 中使用它。
結果就是如今服務間的通訊代碼變成了以下這樣:
GraphQL 模型的 API 包裹器是徹底從 graphene schema 自動生成的。因此,服務甚至不須要模型文件的副本。沒有多餘的請求,身份驗證在後臺透明處理,字段在訪問時會被延遲解析。
如今,在這樣的環境中,成爲一個好的 API 「公民」就會有一些要求了。後臺 API 大多能夠作任何它們想作的事情,可是在如何進行緩存和權限檢查的時候它們必須發揮很好的做用。咱們在後端 APIs 中使用的規則以下:
在 REST API 中返回嵌套的對象是減小請求數量的一個很好的方法。可是這也讓緩存很是困難,並可能致使獲取多餘的資源,這正是 GraphQL 應該對抗的。一般狀況下,咱們避免大的,複雜的請求,而更偏向於稍多可是容易緩存的,更加扁平化的請求。
有時候性能要求超過了簡單性的要求,那咱們就能夠返回潛逃的對象,例如,在一個 API 應答中包含一個相關聯的嵌套對象的長列表。可是,咱們只在被嵌套對象的權限不比外層對象更嚴格的狀況下這樣作,由於若是不這樣,應答就沒法被緩存。
咱們使用 graphene 和 graphene-django 來實際運行服務器,咱們不使用 graphene-django 自動映射 Django 模型的能力,由於全部的數據都來自外部請求,咱們只使用它來與咱們的堆棧的其他部分兼容並熟悉它。整個網關服務實際上就是一個單獨的 GraphQLView,咱們作了一點小小的擴充來容許咱們對前端作出優化:
GraphQL 對咱們大有益處,可是咱們也犯了不少錯誤。有時候咱們會努力保持咱們的 API 能真正向後兼容,除了性能監控和更好的錯誤報告,還必須爲已棄用的字段投入額外的監控。每次 API 變化就須要手動更新 GraphQL 模型,這是至關乏味的事情;而且爲了經過 GraphQL 使後臺服務的通訊變得很是容易,咱們有時也會打破一些服務的邊界。但最終,它幫助咱們更快地發展,維持了基礎設施核心模型的簡易,並使咱們的團隊更加自動化。
若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。