Netflix 是大规模后端工程的大师课。在无缝播放、定制推荐和跨设备一致性背后,是由 Java 供电的复杂架构。
Netflix 后端服务大部分运行在 Java 上。这可能让观看了 Kotlin、Go、Rust 和响应式框架兴起的工程师感到惊讶。但 Netflix 坚持 Java 不是出于惯性。Java 已经成熟,其周围生态系统也是如此。现代 JVM 提供强大的垃圾收集器。Spring Boot 变得既可扩展又可靠。随着虚拟线程和结构化并发的到来,Java 正在高性能、低延迟系统设计中重新获得地位,而无需响应式复杂性。
GraphQL 架构
在 Netflix 后端核心是联邦 GraphQL 架构。这是所有客户端应用与后端数据交互的主要抽象。模型提供灵活性和隔离:客户端可以精确表达它们需要什么,后端团队可以独立演进它们的服务。
每个来自 Netflix 客户端的 GraphQL 查询(无论是来自智能电视、手机还是浏览器)都到达集中式 API 网关。这个网关解析查询,将其分解为子查询,并将这些路由到适当的后端服务。
每个后端团队拥有一个 Domain Graph Service(DGS),它实现整体 GraphQL 模式的一片。Netflix 的每个 DGS 都是 Spring Boot 应用。
DGS 框架本身构建为 Spring Boot 的扩展。这意味着:
- 依赖注入、配置和生命周期管理由 Spring Boot 处理
- GraphQL 解析器只是带注解的 Spring 组件
- 可观察性、安全、重试逻辑和服务网格集成使用 Spring 机制实现
Netflix 选择 Spring Boot 因为它在规模下经过证明,并且是 Netflix 的长期技术。它也可扩展,因为 Netflix 分层其模块用于安全、指标、服务发现等。
技术演进
从 JDK 8 到 JDK 21+
直到最近,Netflix 的大部分 Java 代码库卡在 JDK 8。问题不是惯性而是锁定。多年前构建的自定义内部应用框架积累了未维护库和过时 API 层。这些依赖有紧密耦合和兼容性问题,使升级超过 JDK 8 变得危险。
打破这个循环需要直接方法。Netflix 自己修补不兼容库,不是重写一切,而是分叉和最小化更新必要部分使其与 JDK-17 兼容。
并行地,公司开始迁移所有 Java 服务(约 3000 个)到 Spring Boot。这不是简单的直接迁移。他们构建自动化工具转换代码、配置服务和标准化部署。
垃圾收集器演进
G1 GC:多年来为 Netflix 服务良好。它在吞吐量和暂停时间之间取得平衡,大多数基于 JVM 的服务默认使用它。但在高并发下,一些服务看到超过一秒的停止世界暂停,长到足以导致 IPC 超时并触发跨依赖服务的重试逻辑。
ZGC:在 JDK 21 中,代 ZGC 最终到来。它带来现代、低暂停垃圾收集器,也理解对象生命周期。效果立竿见影:
- 暂停时间降至接近零,即使在高负载下
- 服务在 GC 暂停期间不再超时
- 更少的垃圾收集停滞导致更少的错误率
- 集群可以在更高 CPU 饱和度下运行
虚拟线程
在 Java 21+ 之前,每个请求处理器运行在单独线程上。对于高吞吐系统,这导致高线程数、膨胀内存使用和调度开销。
随着虚拟线程引入,这些轻量级线程由 JVM 调度而不是 OS,允许阻塞代码扩展而无需垄断资源。基于 DGS 框架和 Spring Boot 构建的服务自动受益。
技术栈
后端语言
- Ruby:Shopify 后端主干
- Rust 和 Go:系统编程语言
- TypeScript:前端一等语言
- Python:ML 管道和分析默认
前端
- React:Admin 界面
- React Native:移动应用
- Remix:全栈 Web 框架
数据库
- MySQL:主要关系数据库
- Memcached:分布式内存缓存
- Redis:队列和后台作业
消息队列
- Kafka:消息和事件分发主干
- 峰值处理 6600 万消息/秒
规模指标
- 黑色星期五:50 亿美元 GMV
- 峰值请求:每分钟 2.84 亿请求
- 总请求:24 小时 1730 亿请求
- 流量:每分钟 12TB 流量
- 数据库查询:峰值每秒 4500 万读
- 数据库写入:事务爆发时每秒 760 万写
- Kafka 消息:每秒 6600 万消息
- 单元测试:每次单体构建 40 万 + 单元测试
- 嵌入处理:每天 2.16 亿嵌入
本文为学习目的的个人翻译,译文仅供参考。
原文链接:How Netflix Runs on Java?。
版权归原作者或原刊登方所有。本文为非官方译本;如有不妥,请联系删除。