OpenAI在构建超大规模实时计算平台的过程中,面临的核心挑战之一是如何让流处理作业适应复杂的多基础设施环境。本部分将深入探讨Flink与Kafka的深度集成、实际业务用例以及平台的高可用设计思路。
Flink与Kafka的高可用集成方案
我们面临的核心挑战是:如何让Flink应用适配OpenAI的Kafka高可用组架构,并构建出真正能容忍Kafka集群中断的流处理作业?
理想方案看似简单——在Source和Sink两端为每个Kafka集群配置连接器。然而,现实很快揭示了问题:当某个Kafka集群宕机,Flink作业会因Kafka Source初始化时元数据请求失败而直接崩溃,毫无容错能力。
为此,我们对Kafka Source进行了定制化改造,将其配置为在元数据请求失败时无限重试。这样,已成功初始化的任务能继续运行,而针对故障集群的任务则会持续重试,既不产出数据,也不会拖垮作业。
进一步地,即使集群宕机,我们也能正常重启Flink作业——它会跳过不可达集群的分区。我们还引入了“看门狗”服务监听配置变化,当集群列表变更时触发作业重启,实现了“运行时重试 + 配置驱动调整”的两层容错。
需要说明的是,该方案目前主要应用于不依赖水印的管道。对于依赖水印的管道,某个Source停止输出会导致水印停滞,理论上可通过设置空闲超时缓解,但此路径我们尚未充分验证。
值得关注的是,Flink社区已提供了更优解——动态Kafka Source。它能将多集群的Kafka源统一抽象为一个Flink Source,支持在运行时动态加载元数据并分配新分区,无需重启作业。这极大地提升了灵活性。我们尚未在生产中使用它,主要原因是PyFlink尚未提供对应的Python封装,以及它在某些细节上仍有局限。我们计划尽快补齐支持。
有了动态Kafka Source,我们便拥有一条清晰路径:即使某个Kafka集群宕机,Flink作业也能无缝消费其他集群的数据。
在Sink端,我们最初尝试用分流函数将数据导向多个集群,但此设计存在结构性缺陷:任一集群的背压会传导至整个作业。我们转而采用了OpenAI内部已广泛使用的生产者代理,将其包装成Flink函数来实现高可用写入。当然,这带来了一些限制:
- 不支持基于键的自定义分区。
- 无法支持事务性写入。
- 引入了额外的性能开销。
未来,我们规划将其重构为真正的开源Sink实现,支持非事务性和事务性写入。非事务性写入的实现相对直接,可构建一个支持故障转移和负载均衡的写入器池。事务性写入则复杂得多,涉及跨集群事务协调等难题,但仍存在可行的技术演进路径。
为什么高可用设计如此关键?
在真实的大规模云原生生产环境中,故障是常态。我们经历过整个区域宕机、光缆被挖断等极端情况。因此,系统必须全栈考虑容错:
- Flink集群可能失效:需支持在多个Kubernetes集群间迁移作业。
- 存储可能丢失:依赖异地复制存储,支持主备切换。
- Kafka集群可能中断:通过高可用组和代理层,确保消费端和生产端均无单点故障。
实际业务用例
脱离场景谈架构意义有限,以下是两个受益于该设计的真实管道:
用例一:实时Embedding生成
管道逻辑直接:接收输入,调用模型服务RPC,输出结果。选择Flink的关键原因在于,需要将结果同步分发到多个下游区域。此场景中,数据新鲜度远比完整性重要,因此系统必须具备容忍单个Kafka集群故障的能力,不依赖水印,接受故障恢复后的数据积压。
用例二:传统ML特征计算
借助类似Chronon的框架,可以用声明式方式定义特征逻辑,系统自动编译为Flink作业。同样遵循“一次计算,到处分发”的范式,因为输入数据跨区域分布,下游应用也可能部署在多区域。这就要求Kafka绝不能成为任一区域的单点故障,否则特征计算的完整性将受威胁。
未来工作方向
我们向社区提交了一系列关于PyFlink的issue和PR。虽然PyFlink成熟度不及Java,但社区响应迅速,对以Python工程师为主的团队极具价值。
除了回馈开源,我们也在提升平台自动化能力:
- 构建统一管理平台:智能决策作业调度、集群扩缩容与自动故障转移。
- 关键体验优化:
- 自助式SQL管道,快速构建流处理逻辑。
- 完善PyFlink对异步I/O、流式Join等功能的支持。
- 提升端到端可靠性,如零停机部署、动态连接器更新。
最终目标是让用户专注业务逻辑,平台扛下所有复杂性。
Q&A 环节精选
问:Flink作业的软件生命周期如何管理?比如上线包含新字段的作业时,是否需要重放TB级历史数据?
答:目前,PyFlink作业默认从Kafka最早偏移量(保留窗口起点)开始消费。Kafka主题默认保留7天数据,因此大多情况下可通过重放7天数据来验证或更新逻辑。对于Schema变更,目前主要通过回填方式重新消费Kafka历史数据。自动化程度有待完善,是否重放、从何处开始仍需手动配置。这是我们平台正在完善的领域。
问:用户编写Python作业的接口是什么?是否集成了Jupyter Notebook?
答:用户接口与开发Python微服务相同,使用PyFlink API编写main.py,使用标准IDE和Python库。测试通常在共享的开发/测试集群中进行,部署到测试环境只需几分钟。
问:PyFlink相比基于JVM的Flink应用,性能开销具体如何?
答:我们尚未进行正式基准测试,但从实际运行看,由于用户逻辑在Python进程执行,PyFlink在CPU和内存消耗上确实更高。对于大规模作业,我们提供混合模式:用Python编排作业拓扑,将核心计算逻辑实现在JVM算子中,以平衡开发效率与性能。
问:如何应对像GPT图像生成上线这样的流量高峰?
答:最大的流量增长通常来自新功能的接入。团队在设计阶段就会与我们沟通,进行容量评估、集群扩容和分区规划。得益于这种前置协作,大多数高流量场景都能被平稳承接。