Netflix採用GraphQL的經驗分享
NetflixOSS是Spring Cloud預設堆疊,他們的實踐走在行業前列,在這篇博文中,他們解釋了為什麼GraphQL很棒,以及成長的痛苦在哪裡。
在這篇文章中,我們將分享我們更新前端架構的過程以及將GraphQL引入Marketing Tech系統的經驗。
我們的釋出平臺的廣告管理應用在內部被稱為Monet,用於增強廣告製作並自動管理外部廣告平臺上的營銷廣告系列。Monet幫助推動增量轉換,與我們的產品互動,總體而言,向全世界的使用者展示我們的內容和Netflix品牌的豐富故事。為此,首先,它有助於擴充套件和自動化廣告製作並管理數百萬個廣告素材排列。其次,我們利用各種訊號和彙總資料,例如瞭解Netflix上的內容流行度,以實現高度相關的廣告。
我們的總體目標是使我們在所有外部發布渠道上的廣告能夠與使用者產生共鳴,並且我們不斷嘗試提高我們這樣做的有效性。
問題
當我們開始時,Monet的React UI層訪問了由Apache Tomcat伺服器支援的傳統REST API。隨著時間的推移,隨著應用程式的發展,我們的用例變得更加複雜。簡單頁面需要從各種來源中提取資料。為了更有效地將此資料載入到客戶端應用程式,我們首先嚐試對後端的資料進行非規範化。管理這種非規範化變得難以維護,因為並非所有頁面都需要所有資料。我們很快遇到了網路頻寬瓶頸。瀏覽器需要獲取比以往更多的非規範化資料。
為了減少傳送給客戶端的欄位數量,一種方法是為每個頁面構建自定義端點; 這是一個相當明顯的非首選項。我們選擇GraphQL作為應用程式的中間層,而不是構建這些自定義端點。
我們還認為Falcor是一種可能的解決方案,因為它在許多核心用例中已經在Netflix上取得了很好的成果並且使用量很大,但強大的GraphQL生態系統和強大的第三方工具使得GraphQL成為我們用例的更好選擇。此外,隨著我們的資料結構越來越以圖形為導向,它最終變得非常自然。新增GraphQL不僅解決了網路頻寬瓶頸問題,而且還提供了許多其他優勢,幫助我們更快地新增功能。
優點
我們已經在NodeJS上執行GraphQL大約6個月,並且它已經證明可以顯著提高我們的開發速度和整體頁面載入效能。以下是自我們開始使用以來對我們有益的一些好處。
1.重新分配負載和有效負載最佳化
通常,某些機器比其他機器更適合某些任務。當我們新增GraphQL中間層時,GraphQL伺服器仍然需要呼叫與客戶端直接呼叫的相同的服務和REST API。現在的區別在於大多數資料在同一資料中心內的伺服器之間流動呼叫。這些伺服器到伺服器的呼叫具有非常低的延遲和高頻寬,與來自瀏覽器的直接網路呼叫相比,前者效能是後者8倍。
因此,從GraphQL伺服器到客戶端瀏覽器的資料傳輸的最後一英里雖然仍然是一個效能慢點,現在採取GraphQL以後可以減少到一次網路呼叫。由於GraphQL允許客戶端只選擇它需要的資料,我們獲得了明顯更小的有效負載。頁面載入變得更快,尤其是在資料受限的行動網路上,我們的應用程式使用的記憶體更少。這些更改確實以提高伺服器利用率為代價來執行資料獲取和聚合。
2.可重複的抽象
軟體開發人員通常希望使用可重用的抽象而不是單一用途的方法。使用GraphQL,我們定義每一段資料,並定義它與我們系統中其他資料的關係。當消費者應用程式從多個源獲取資料時,它不再需要擔心與資料連線操作相關聯的複雜業務邏輯。
我們只在GraphQL中定義一次實體:目錄,廣告素材和評論。我們現在可以根據這些定義構建多個頁面的檢視。相同的圖模型可以為多個檢視提供動力,而無需進行任何伺服器端程式碼更改。
3.鏈式系統
許多人專注於單一服務中的型別系統,但很少跨服務。一旦我們在GraphQL伺服器中定義了實體,我們就會使用auto codegen工具為客戶端應用程式生成TypeScript型別。我們的React元件的道具接收型別以匹配元件正在進行的查詢。
由於這些型別和查詢也是針對伺服器模式進行驗證的,因此伺服器的任何重大更改都將被使用該資料的客戶端捕獲。將多個服務與GraphQL連結在一起並將這些檢查掛鉤到構建過程中,可以在部署錯誤程式碼之前捕獲更多問題。理想情況下,我們希望從資料庫層一直到客戶端瀏覽器具有型別安全性。
4.DI / DX - 簡化開發
建立客戶端應用程式時常見的問題是UI / UX,但開發人員介面和開發人員體驗對於構建可維護應用程式同樣重要。在GraphQL之前,編寫一個新的React容器元件需要維護複雜的邏輯,以便為我們需要的資料發出網路請求。開發人員需要考慮一個資料如何與另一個資料相關,如何快取資料,是否並行或按順序進行呼叫以及Redux中儲存資料的位置。使用GraphQL查詢包裝器,每個React元件只需要描述它所需的資料,並且包裝器會處理所有這些問題。樣板程式碼更少,資料和UI之間的關注點更清晰。這種宣告性資料獲取模型使React元件更容易理解,
5.其他福利
還有一些其他較小的好處,我們也注意到了。首先,如果GraphQL查詢的任何解析程式失敗,則成功的解析程式仍會將資料返回到客戶端,以儘可能多地呈現頁面。其次,後端資料模型大大簡化,因為我們不太關心客戶端的建模,並且在大多數情況下可以簡單地為原始實體提供CRUD介面。最後,測試我們的元件也變得更容易,因為GraphQL查詢可以自動轉換為我們測試的存根,我們可以獨立於React元件測試解析器。
成長的煩惱
我們向GraphQL的遷移是一種簡單的體驗。我們為構建網路請求和轉換資料而構建的大多數基礎架構都可以輕鬆地從我們的React應用程式轉移到我們的NodeJS伺服器,而無需更改任何程式碼。我們甚至最終刪除了比我們新增的更多程式碼。但是,與任何向新技術的遷移一樣,我們需要克服一些障礙。
1.自私的解析器
由於GraphQL中的解析器旨在作為與其他解析器無關的獨立單元執行,因此我們發現它們對相同或類似的資料進行了許多重複的網路請求。我們透過將資料提供程式包裝在一個簡單的快取層中來解決這種重複問題,該快取層將網路響應儲存在記憶體中,直到所有解析器完成。快取層還允許我們將對單個服務的多個請求聚合成一次性所有資料的批次請求。解析器現在可以請求他們需要的任何資料,而無需擔心如何最佳化獲取它的過程。
2.我們編織的網路多麼糟糕
抽象是提高開發人員效率的好方法......直到出現問題。毫無疑問,我們的程式碼中存在錯誤,我們不希望使用中間層來混淆根本原因。GraphQL會自動編排對其他服務的網路呼叫,從而隱藏使用者的複雜性。伺服器日誌提供了一種除錯方法,但它們仍然是透過瀏覽器的網路選項卡從自然除錯方法中刪除的一步。為了使除錯更容易,我們將日誌直接新增到GraphQL響應有效負載,該負載公開了伺服器正在進行的所有網路請求。啟用除錯標誌後,您將在客戶端瀏覽器中獲得與瀏覽器直接進行網路呼叫時相同的資料。
3.打破型別
傳遞物件是OOP的全部內容,但不幸的是,GraphQL打破了這種正規化。當我們獲取部分物件時,就不能使用那些返回完整物件的方法和元件。當然,您可以手動轉換物件並希望獲得最佳效果,但是您會失去型別系統的許多好處。幸運的是,TypeScript使用duck typing,因此調整這些方法返回只需要的物件屬性。定義這些更精確的型別需要更多的工作,但總體上提供更大的型別安全性。
接下來是什麼
我們仍然處於探索GraphQL的早期階段,但到目前為止它是一次積極的體驗,我們很高興接受它。這項努力的關鍵目標之一是幫助我們在系統日益複雜的同時提高開發速度。我們希望投資graph 資料模型,以便隨著時間的推移,隨著更多邊緣和節點的增加,我們的團隊將更加高效,而不是陷入複雜的資料結構。即使在過去的幾個月裡,我們發現現有的graph模型已經變得足夠強大,我們不需要任何graph 更改就可以構建一些功能。它確實使我們更有成效。
相關文章
- 採用 GraphQL 的技術經驗:營銷技術活動
- [譯] 我們採用 GraphQL 技術的經驗:營銷技術活動
- GitHub CSP應用的經驗分享Github
- Netflix Conductor等開源工作流引擎的使用經驗分享 | 駭客新聞
- Netflix釋出用於Spring Boot的GraphQL的開源服務框架DGSSpring Boot框架
- Spring Boot和Netflix DGS的GraphQL原始碼案例Spring Boot原始碼
- 經驗分享
- 經驗分享:採用事件溯源的誤區(以及我們是如何避免的)事件
- 如何改善應用啟動效能 | Facebook 應用的經驗分享
- 6條經過驗證的創業經驗分享創業
- 繼全面採用Node.js以後,PayPal分享大幅度踩坑GraphQL心得 - Mark StuartNode.js
- 奈飛Netflix兩年資料工程經驗 - XInran
- Polymer使用經驗分享
- 【高中經驗分享】2021.11.29
- Spring GraphQL與Netflix領域圖服務框架整合Spring框架
- .NET 6 Minimal API 的經驗分享API
- GraphQL分享理論篇
- Java 應用壓測效能問題定位經驗分享Java
- 分享抖音交流經驗
- 徵求護眼經驗分享
- 遊引力出海經驗分享
- DDD經驗:分享工作,分享決策 – Jessitron
- 微信群控系統的應用和實戰經驗分享
- 實用的管理經驗
- 經驗分享:eBay的API智慧設計API
- PagerDuty的API開發經驗分享 – IncrementAPIREM
- 視覺化—gojs 超多超實用經驗分享(一)視覺化GoJS
- 安卓應用效能除錯和優化經驗分享安卓除錯優化
- 視覺化—gojs 超多超實用經驗分享(三)視覺化GoJS
- 視覺化—gojs 超多超實用經驗分享(四)視覺化GoJS
- TypeScript 重構 Axios 經驗分享TypeScriptiOS
- Native轉型Flutter經驗分享Flutter
- 考研經驗分享(上岸南理工)
- 封裝 avm 元件經驗分享封裝元件
- 精益生產經驗分享
- C# 學習經驗分享C#
- 經驗分享:HelloFresh在生產中執行Istio的經驗教訓 - Craig HuberAI
- 一份經過時間檢驗的 Laravel PHPUnit 測試經驗分享LaravelPHP