寫在前面
上一篇文章中,我們講解了網飛當前的架構,但網飛的架構并不是一開始就是這樣的,而是不斷演進發展才是當前的樣子。
這篇文章我們就來講講網飛架構的演進過程。
第一階段:Zuul Gateway + REST API
- 使用 Zuul 作為API網關,
單一前門
- 設備調用網關,網關扇出到多個微服務
而在這個架構下,會遇到一些問題:
不同設備有不同的數據需求
,Web端、App端、TV端所需要的數據結構不一樣單一REST API無法滿足所有設備
,導致api變多且難以維護,要么獲取過多數據,要么需要多次調用- 設備特定的優化需求難以進行
第二階段:BFF(Backend For Frontend)模式
為了處理不同設備的差異化數據需求和減少網絡調用,網飛采用了Backend For Frontend (BFF)
模式。每個前端都有專屬的后端。
- UI開發者編寫和維護 Groovy腳本
定制化獲取數據。
- Groovy 腳本部署在API服務器上,通過 Java 調用gRPC/REST服務,并使用 RxJava 和容錯庫 Hystrix 處理扇出中的
線程管理和容錯問題
。
Groovy 是 ?后端導向的語言?,主要服務于 JVM 平臺的后端邏輯、自動化腳本和構建工具鏈
然而,這種 BFF 模式存在局限性:
- 需要維護大量的腳本,每個終端一個腳本,維護復雜。
- 反應式編程本身學習曲線陡峭且復雜
- UI 開發者不喜歡用 Groovy/Java/RxJava
第三階段:GraphQL Federation + Java Version 21
- 采用DGS微服務:基于 GraphQL 的 SprintBoot 服務
- API 網關處理GraphQL
GraphQL Federation 取代了 BFF,因為客戶端可以通過 GraphQL 精確選擇所需的字段,解決了 REST API 過度或不足獲取數據的問題
,使得一個 API 可以服務于不同的 UI。這意味著 UI 工程師不再需要進行服務器端開發來獲取自己所需要的數據。
Java 版本升級
從 Java 8 遷移到 Java 17 后,得益于G1垃圾收集器的改進,CPU 使用率降低約 20%,這是一個非常恐怖的優化,會省下非常多的云資源。這些jdk的升級其實很難做,需要兼顧每一個第三方包。是一項很繁瑣的工作。
舉個視頻中的例子,網飛處理Spring Boot 3升級中的Jakarta EE 命名空間的變化,Spring Boot 3 是基于JDK 17,并且從javax
切換到了jakarta.ee
。對于應用程序而言,這只是簡單的查找并替換。
但對于依賴 javax 并且已經編譯成JAR包的老舊庫來說,而這些老舊庫已經找不到源代碼了
但還在使用,運行時仍然會嘗試尋找 javax.servlet.Filter。但此時,環境提供的卻是 jakarta.servlet.Filter。由于包名和類名不匹配,即使功能相同,JVM也無法找到對應的類,從而導致運行時錯誤。
針對這種二進制不兼容性
的情況,Netflix利用 Gradle transforms 來解決。通過 Gradle插件工具,在依賴包下載時的 artifact resolution time 進行字節碼重寫
,相當于二進制的查找并替換,將所有javax 替換為 jakarta。
由于這些API在功能上沒有變化,只是命名空間改變,所以這種重寫是安全的。而這個工具已作為Netflix Nebula生態系統的一部分開源。
此外網飛目前正測試和推廣 Java 21+,Java 21+ 的 ZGC 垃圾收集器(低暫停時間)和虛擬線程(Virtual Threads)特性都非常優秀。 虛擬線程結合結構化并發很有可能完全取代反應式編程(如 RxJava),簡化并發代碼的開發和調試。