- 原文地址:Our learnings from adopting GraphQL: A Marketing Tech Campaign
- 原文作者:Netflix Technology Blog
- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:Sam
- 校對者:lianghx-319
在之前的部落格文章中,我們對營銷技術團隊的一些應用程式提供了高階概述,我們這麼做是為了推動全球廣告業務實現 體量化和智慧化,使得廣告可以通過像紐約時報,Youtube 等網站覆蓋成千上萬的使用者。在這篇博文中,我們將分享關於我們更新前端架構的過程和在營銷技術團隊中引入 GraphQL 的經驗。
我們用於管理建立和裝配廣告到外部部署平臺的核心應用程式在我們內部被稱為 Monet。它用於增強廣告的建立和自動化管理在外部廣告平臺的營銷活動。Monet 幫助推動增量轉化,通常是和我們的產品進行互動,為全球各地的使用者展示關於我們內容和 Netflix 品牌的精彩故事。為此,首先,它幫助擴充套件和自動化廣告產品,並且管理數百萬廣告素材佇列。其次,我們借用多種訊號和彙總資料(例如瞭解在 Netflix 上的內容流行度)以實現高度相關的廣告。我們總體目標是確保我們所有在外部發布頻道的廣告能夠很好的引起使用者的共鳴,並且我們不斷嘗試提高我們這麼做的有效性。
Monet 和高階營銷技術流程
在我們開始的時候,Monet 的 React UI 層訪問的是由 Apache Tomcat 服務提供的傳統 REST API。隨著時間的推移,我們應用程式的發展,我們的用例變得更加複雜。簡單的頁面需要從各種來源中獲取資料。為了更加高效的在客戶應用程式中載入這些資料,我們首先嚐試在後端對資料進行非規範化處理。由於不是所有頁面都需要所有這些資料,管理這些非規範化(的資料)變得難以維持。我們很快就遇到了網路頻寬瓶頸。瀏覽器需要獲取比以往更多的非規範化資料。
為了減少傳送給客戶端的欄位數量,一種方法是為每個頁面建立自定義端點;這是一個明顯不切實際的想法。我們選擇使用 GraphQL 作為我們應用的中間層,而不是建立這些自定義端點。我們也考慮過把 Falcor 作為一個可能的解決方案,畢竟它在 Netflix 的很多用例中展現出很好的成果並且大量的使用,但是 GraphQL 健壯的生態體系和強大的第三方工具庫使得 GraphQL 成為我們用例更好的選擇。此外,隨著我們資料結構越來越面向圖形化,使用 GraphQL 最終適配會非常自然。新增 GraphQL 不僅解決了網路頻寬瓶頸問題,而且還提供了許多其他優勢,幫助我們更快地新增功能。
使用 GraphQL 架構的前後對比。
優勢
我們已經在 NodeJS 上執行 GraphQL 差不多六個月了,並且它已經被證實可以顯著提高我們的開發速度和總體提升頁面載入效能。這裡是自從我們使用 GraphQL 實踐給我們帶來的一些好處。
重新分配負載和有效負載優化
通常,某些機器比其他機器更適合做一些任務。當我們新增了 GraphQL 中間層時,GraphQL 伺服器仍然需要呼叫和客戶端直接呼叫的相同的服務和 REST API。現在的區別在於大多資料在同一資料中心的伺服器之間流動。這些伺服器和伺服器之間的呼叫是非常低延遲和高頻寬的,比起直接從瀏覽器發起網路請求有 8 倍的效能提升。從 GraphQL 伺服器傳送資料到客戶瀏覽器的最後一段雖然仍是一個慢點,但至少減少成單個網路請求。由於 GraphQL 允許客戶端只選擇它需要的資料,所以我們最終可以獲取明顯更小的有效負載。在我們的應用程式中,頁面之前要獲取 10M 的資料,現在接收大約 200KB 即可。頁面載入變得更快,特別是資料受限在行動網路上,並且我們的應用使用的記憶體更少。這些更改確實以提高伺服器利用率為代價來執行資料獲取和聚合,但是每個請求所花費的額外一點伺服器毫秒時間遠比不上更小的客戶端有效負載。
可複用的抽象
軟體開發者通常希望使用可複用的抽象而不是單一目的方法。使用 GraphQL,我們定義每段資料一次,並定義它與我們系統中其他資料之間的關係。當消費者應用程式從多個源獲取資料時,它不再需要擔心與資料連線操作相關聯的複雜業務邏輯。
考慮接下來的例子,我們在 GraphQL 中只定義例項一次:catalogs(類別)、creatives(素材)和 comments(評論)。現在我們可以由這些定義建立多個頁面檢視。客戶端上的一個頁面(類別檢視)定義了它想要所有的評論和素材在一個分類裡,而另一個客戶端頁面(素材檢視)想要知道素材相關聯的類別,以及所有和它相關的評論。
GraphQL 資料模型的靈活性,用於表示來自相同底層資料的不同檢視。
同一個 GraphQL 模型就可以滿足上述兩個檢視的需求,而不用做任何伺服器端的程式碼修改。
鏈式系統
很多人專注於單一伺服器裡的型別系統,但很難有跨服務的。一旦我們在 GraphQL 伺服器中定義了例項,我們使用自動程式碼生成器工具為客戶端程式生成 TypeScript 型別。我們的 React 元件屬性接收類別以匹配元件正在進行的查詢。由於這些類別和查詢也是針對伺服器模式進行驗證的,因此伺服器的任何重大更改都將被使用該資料的客戶端捕獲。將多個伺服器和 GraphQL 連結在一起並將這些檢查掛載到構建過程中,可以讓我們在釋出程式碼前捕獲更多錯誤。理想情況下,我們希望從資料層一直到客戶端瀏覽器層都是具有型別安全性的。
從資料庫到後端到客戶端程式碼的型別安全。
DI/DX — 簡化開發
當建立客戶端應用程式時普遍需要考慮 UI/UX,但是開發者介面和開發者體驗一般只是側重於構建可維護應用程式。在使用 GraphQL 之前,編寫一個新的 React 包裝元件需要維護複雜的邏輯,以便為我們所需的資料發起網路請求。開發者需要關心每部分資料之間的依賴,資料該怎麼快取,以及是否做併發或佇列請求,還有在 Redux 的什麼位置儲存資料。使用 GraphQL 的查詢封裝(wrapper),每個 React 元件只需描述它所需要的資料,然後由封裝(wrapper)去關心所有這些問題。這樣就會是更少的引用程式碼和更清晰的資料與 UI 之間的關注點分離。這種定義資料獲取的模組可以讓 React 模組更容易理解,並且能夠為部分描述文件提供服務知道元件具體在做什麼。
其他優勢
我們也留意到其他一些小的優勢。首先,如果任何 GraphQL 的查詢解析器失敗了,已經成功的解析器仍然會返回資料到客戶端渲染出盡可能多的頁面。其次,由於我們更少的關心客戶端模型,後端資料模型就簡化了很多,在大多數情況下,只需提供一個 CRUD 介面的原始實體。最後,基於 GraphQL 的查詢會自動為我們的測試進行存根轉變,測試我們的元件也會變得很簡單,並且我們可以把解析器從 React 元件中獨立出來進行測試。
使用痛點
我們遷移到 GraphQL 是一個直截了當的過程。我們構建的大多數用於做網路請求和傳輸資料的基礎架構在不做任何程式碼修改的情況下可以很容易在 React 應用和我們 NodeJS 服務之間做到可傳遞。我們甚至最終刪除的程式碼比我們加的多。但是在遷移到任何新的技術這條路上,總會有一些需要我們越過的障礙。
自私的解析器
由於 GraphQL 裡的解析器定義為獨立執行的單元,而不用關心其他解析器在做什麼,我們發現他們會對相同或類似的資料發起很多重複的網路請求。我們通過將資料提供者包裝在一個簡單的快取層中來避免這種重複,該快取層將網路響應儲存在記憶體中,直到所有解析器都完成。快取層還允許我們將多個對單個服務的請求聚合為一次對所有資料的批量請求。解析器現在可以請求他們需要的任何資料,而不必擔心如何優化獲取資料的過程。
新增快取以簡化來自解析器的資料訪問
我們編寫的繁雜網路
抽象是提高開發人員效率的好方法 —— 直到出現問題為止。毫無疑問,我們的程式碼中會有bug,我們不想用中間層混淆(bug 產生的)根本原因。GraphQL 將自動編排對其他服務的網路呼叫,對使用者隱藏複雜性。雖然伺服器日誌提供了一種除錯方法,但是它們仍然比通過瀏覽器的 network 選項卡進行除錯的自然方法少了一步。為了讓除錯更簡單,我們直接將日誌新增到 GraphQL 響應有效負載中,它公開了伺服器發出的所有網路請求。當啟用除錯標誌時,你將在客戶端瀏覽器中獲得與瀏覽器直接進行網路呼叫時相同的資料。
拆分型別
傳遞物件是物件導向程式設計(OOP)的全部,但不幸的是,GraphQL 將對這個正規化造成衝擊。當我們獲取部分物件時,這些資料不能用於需要完整物件的方法和元件中。當然,你可以手動強制轉換物件並抱著最好的希望,但是你將失去型別系統的許多好處。幸運的是,TypeScript 使用了 duck typing(譯者注:鴨子型別,關注點在於物件的行為,能作什麼;而不是關注物件所屬的型別。duck typing),所以只需要對它們真正需要的物件屬性方法進行調整是最快的修復方式。雖然定義更精確的型別需要做更多的工作,但是總體上確保了更大的型別安全性。
接下來是什麼
我們仍然處於探索 GraphQL 的早期階段,但到目前為止都是一種積極的體驗,我們很高興能夠接受它。這項工作的一個關鍵目標是,隨著我們的系統變得越來越複雜,(它)幫助我們提高開發速度。我們不希望被複雜的資料結構所困,而是希望在圖形資料模型上進行投資,隨著時間的推移,隨著更多的邊緣和節點的新增,我們的團隊會更加高效。甚至在過去的幾個月裡,我們已經發現我們現有的圖形模型已經足夠健壯,我們不需要任何圖形更改就可以構建一些特性。它確實讓我們變得更有效率。
我們的視覺化 GraphQL 模型
隨著GraphQL的不斷髮展和成熟,我們期待可以從社群中使用它構建和解決的所有令人驚歎的東西中學習。在實現級別上,我們期待使用一些很酷的概念,比如模式縫合,它可以使與其他服務的整合更加直接,並節省大量開發人員的時間。最重要的是,我們很開心地看到在公司很多團隊發現 GraphQL 的潛力並開始採用它。
如果你已經做到了這一點,並且你也有興趣加入 Netflix 營銷技術團隊來幫助克服我們獨特的挑戰,看看我們頁面上列出的空缺職位。
我們正在招聘!
如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。