写点什么

京东这样用 Flink:适应业务的才是最好的

  • 2022-07-28
  • 本文字数:3692 字

    阅读完需:约 12 分钟

京东这样用 Flink:适应业务的才是最好的

嘉宾 | 付海涛

编辑 | 贾亚宁


Apache Flink 功能强大,支持开发和运行多种不同种类的应用程序。事实证明,Flink 已经可以扩展到数千核心,其状态可以达到 TB 级别,且仍能保持高吞吐、低延迟的特性。出于对云原生和 Flink 之间的关系,以及最新提出的流式数仓这个概念的好奇,我们特意邀请了付海涛老师。


付海涛老师目前在京东担任资深技术专家,日常工作包含 Flink 引擎的优化增强、容器环境任务的优化和智能运维等;同时老师也是 QCon+ 案例研习社Flink 在实时计算应用场景中的落地实践」专题的出品人,一起来看看他的独家理解吧。

一、如何快速恢复作业


我们日常的工作中,容器环境复杂多变,pod 被驱逐或重启时有发生,这些都会导致任务重启恢复,对业务造成较大影响,特别是对于很多交易类的重要业务来说是不可接受的。为此,我们进行了作业快速恢复的定制优化,主要从两方面着手:


  1. 针对容器环境,加快 pod 异常(被驱逐或重启)的感知速度,迅速恢复作业。


在官方的默认实现中,如果 pod 发生异常,可能会从故障 pod 下游算子感知网络连接断开异常或者 jobmanager 感知 taskmanager 心跳超时两个路径感知,无论哪个路径,所需总时长会比心跳超时多一些,时间较长。


为此,我们优化了 pod 异常感知的速度,在 pod 异常被停止时或感知到容器内 taskmanager 进程异常退出时,主动通知 jobmanager 哪个 taskmanager 发生了异常,这样一来,jobmanager 就可以在 pod 异常的时候第一时间得到通知,并及时进行作业的故障恢复。我们讲这项优化在典型场景下进行了测试,集群有空余资源时,任务 failover 的时长从原来的 60 多秒缩短到几秒,效果还是比较明显的。


  1. 减小 pod 异常对作业的影响范围。


虽说社区版在 1.9 之后,提供了基于 region 的局部恢复策略,在 Task 发生故障时,只重启故障 Task 关联 region 内的 Task,在有的场景下可以减小影响;但是很多时候一个作业的算子之间都是 rebalance 或者 hash 等全连接的方式,region 策略也起不到太大作用。为此,针对允许少量丢数的业务场景,我们开发了基于故障 Task 的单点恢复策略,Task 发生故障时只恢复该故障 Task,非故障 Task 不受影响,从而减小故障 Task 对整个作业的影响范围。


通过这项优化,在线应用取得了不错的效果,其对作业的影响范围大大减少(取决于具体的作业,能够减少为原来的几十分之一到几百分之一),避免了业务的断流,恢复时长也大大降低了。

二、流批一体在京东的实践


流批一体是 Flink 社区最近几年比较火的一个方向,它可以解决流批割裂带来的高开发和运维成本、数据口径不一致等业务问题。对于流批一体,我们团队也进行了一些探索和实践,并在部分的实际业务场景中进行了落地。


要在实际业务场景中应用流批一体,需要满足几个前提条件:


  1. 在生产环境,同一个口径指标需要分别用流任务进行实时加工和批任务进行离线加工,此时才需要考虑是否要做流批一体;

  2. 实时加工和离线加工的数据模型大体一致;

  3. 实时加工和离线加工的逻辑可以复用。


这里举一个实际案例,有个业务团队需要针对流量买卖黑产进行舆情分析,它的原有架构如下:



从图中可以看到,这是一个典型的 Lambda 架构:源端通过爬虫爬取了一些相关信息并写到 JMQ,在数据同步到 JDQ 后,通过 Flink 进行处理,写入到下游的 JDQ,这是实时链路;与此同时,通过 DTS 数据传输服务将上游 JDQ 的数据同步到 HDFS 落一份 Hive 表,然后通过 Hive 表去进行离线的数据加工,这是离线链路。


此外,该业务离线、实时加工的模型和计算逻辑是一致的,并且端到端的实时性要求不高,可接受分钟级别延时。


基于此业务特点,我们直接把中间存储环节从 JDQ 换成了 Iceberg,然后通过 Flink SQL 去增量读取,实现业务的加工逻辑,这样完成了流批两条链路的完全统一,其中 Iceberg 表中的数据也可以供 OLAP 去查询或离线去做进一步加工。


流批一体架构

通过上图的架构,不仅实现了计算层面的流批统一,也实现了存储层面的流批统一。经过业务方实际应用反馈,整个链路的时延在一分钟左右,存储、计算成本显著降低,开发、运维成本降低 30%,获得了不错的实际业务效果。

三、流式数仓


流式数仓是 Flink Forward Asia 2021 主题演讲中提出的下一步的重要发展方向,是对近几年比较火的流批一体大方向下对数仓场景落地方案的思考。它可以解释为“make data warehouse streaming”,就是让整个数仓的数据全实时地流动起来,且是以纯流的方式而不是微批(mini-batch)的方式流动,从而让当前业界主流数仓架构再进阶一层,实现真正端到端全链路的实时化分析能力。


从目前来看,业内还没有这样一个端到端全流式链路的成熟解决方案,虽说可以通过一些纯流的方案 + 纯交互式查询方案 + 离线数仓方案(比如:Flink + Kafka + ClickHouse + HBase + Hive…)叠加起来达到近似效果,但这样系统复杂性又太高了。但如果业务对时延要求不高,可以通过 Flink+ 数据湖(比如 Iceberg)的方案作为替代方案,可以解决很多场景的问题。



流式数仓要做到在实现高时效性的同时,保证整个架构对于开发和运维人员的简洁。要达成这个目标,Flink 需要一个与本身流批一体理念真正配套的存储,于是社区提出了新的 Dynamic Table Storage,即具备流表二象性的存储方案。


数仓的分层数据全部放到 Flink Dynamic Table 中,通过 Flink SQL 实时串联整个数仓的分层,数据在各个分层间进行实时流动,并可以对历史数据实现离线修正;与此同时,用户可以利用 Flink SQL 实时探索和分析 Dynamic Table 中流动的数据,从而真正做到实时离线分析一体化:统一的 SQL、统一的数据存储、统一的计算框架,可以实现全链路数据实现秒级和毫秒级的实时流动,并且所有流动中的数据皆可分析,没有任何数据盲点,用一套 API 就完成所有的数据分析。


这样一来,实时、离线以及交互式查询分析、短查询分析等场景,都可以用它来统一解决。目前社区已经初步走通整个流程,但真正要实现全实时链路且足够稳定,还需要解决一系列工程问题,可以持续关注社区发展并参与进去。

四、云原生如何给 Flink 赋能


Flink 和云原生是密不可分的两个场景,云上环境和弹性可以给 Flink 计算更多的空间,加速其应用和普及;同时,面向云原生,Flink 也在云原生的趋势下对部署架构和资源管理方式持续演进优化,以更适应云原生的场景并发挥更好的性能。


首先云原生容器化具有优异的 DevOps 能力、资源隔离、统一调度等特性,可以快速部署 Flink 应用,并提供更好的资源管理和隔离机制,避免应用的互相影响,提升计算的稳定性。


其次云原生弹性化调度的能力,可以使 Flink 应用按需动态扩缩容,降本增效。当然这也需要对 Flink 进行相应的调整和优化。为此,Flink 社区也进行了适应云原生持续的升级迭代,能够更加适应云原生环境下的运行。比如,在 Flink 1.13 中支持了响应式伸缩的功能,可以根据云上资源动态扩缩容的变化在计算拓扑上以自适应模式调整并发,从而适应云上资源变化。


最后,云原生服务混部和资源共享能力,支持将不同负载的服务比如 Flink 流批计算、在线服务、机器学习等服务混合在一起,获得更好的资源利用。

五、Flink 避坑指南


平台建设过程:根据业务特点选择合适的作业部署模式,并考虑如何迭代升级 Flink 的版本,这些会在很大程度上影响后续平台的运维成本。


目前 Flink 支持 session、per-job、aplication 三种部署模式,都有各自不同的优缺点和适用场景,需要做一个权衡。我们平台起初有很多业务有一个集群跑多个作业的业务需求,为此选择了 session 模式,采用该模式预分配资源,提交作业可以直接运行,省去了每次分配资源的开销,适用于对延迟非常敏感的业务,特别是在紧急情况热备切换时特别有用。


不过,这与此同时也带来了新的问题和挑战,比如同一集群的多个任务之间会存在资源抢占,作业存在内存泄漏时多次提交会导致 OOM 等问题,需要付出额外的努力去定制优化引擎来解决这些问题。


此外,社区版 Flink 的版本迭代升级很快,不同版本之间可能会存在不完全兼容的情况,在跟随社区步伐升级 Flink 版本后,平台会出现多个 Flink 版本并存的问题,这会带来较大的运维成本,如何推动业务平滑升级 Flink 版本、减少运维压力是一项具有挑战性的工作。一种有效的做法是可以采用新作业使用新版本、旧作业分级处理(对于不重要业务,优先推动升级,在解决完跨版本不兼容问题后,再升级重要业务)的方式来解决这个问题。


如果要上云,除了基本的上云适配,还需要额外关注容器化带来的性能损耗(比如网络、磁盘等),并注意容器化环境相比物理机环境产生的一些新的问题(比如容器网络连通问题、容器驱逐或重启频繁、OOM killed 等),这些与物理机环境运行有较大差异,需要结合具体容器环境及业务进行针对性优化。


最后是多关注和参与社区。在遇到问题的时候,可以去社区多多交流,很多问题都是大家之前遇到过的,会有一些现成的经验可以参考,少走一些弯路;同时将一些方案或特性反馈给社区,也可以形成良性正向循环。

嘉宾介绍


付海涛  京东资深技术专家


拥有多年中间件、互联网云平台和大数据开发经验,对分布式计算、容器、微服务等有较深入的理解。2018 年加入京东,主要负责实时计算引擎 Storm、Flink 的相关优化和开发工作。

2022-07-28 11:044638

评论

发布
暂无评论
发现更多内容

JavaWeb快速入门--Tomcat(1),关于Java性能优化的几点建议

Java 程序员 后端

Java个人学习之旅(第十天),java就业班百度网盘

Java 程序员 后端

Java中的泛型,java程序执行过程与编译原理

Java 后端

Java中高级核心知识全面解析-容器(ArrayList)

Java 程序员 后端

JavaWeb Ajax详解,java64位3下载百度云盘

Java 程序员 后端

JavaWeb学习总结18--redis学习,java高级程序设计作业系统

Java 程序员 后端

Java内存问题 及 LeakCanary 原理分析,mybatis架构设计层次

Java 程序员 后端

Java基础 - 单例(饿汉、懒汉),Runtime类,java教程推荐学客巴巴

Java 程序员 后端

java中常用单词系列(一),最新Java高级面试题汇

Java 程序员 后端

Java中的几种线程池详解,rabbitmqpdf百度云

Java 程序员 后端

Java初学01:学习路线,java基础入门清华大学出版社

Java 程序员 后端

Java反射的深入浅出,mongodb优化面试

Java 程序员 后端

JAVA代码审计之Shiro反序列化漏洞分析,浦发银行Java开发笔试题

Java 程序员 后端

Java几种常用JSON库性能比较,java接口开发面试

Java 程序员 后端

JavaScript基础大总结,对于java开发岗位的理解面试

Java 程序员 后端

JavaWeb快速入门--JavaScript(2),java面试题库及答案

Java 程序员 后端

Java中当对象不再使用时,不赋值为null会导致什么后果?

Java 程序员 后端

Java之Spring基础与IOC,java实用教程第五版答案第四章

Java 程序员 后端

Java中高级核心知识全面解析——Dubbo,java语言入门自学书

Java 程序员 后端

Java 多线程 —— 同步代码块(1),狂神说docker进阶笔记

Java 程序员 后端

Java 常见的 30 个误区与细节!,java面试刷题

Java 程序员 后端

JAVA-数据结构与算法,mysql数据库应用与实践教程

Java 程序员 后端

Spring是如何自动注入多类型的?

编号94530

spring bean @Autowired 自动注入

Java 多线程 —— 同步代码块,联通java开发面试

Java 程序员 后端

Java中高级核心知识全面解析——常用框架(Spring常用注解

Java 程序员 后端

Java 必须掌握的 12 种 Spring 常用注解!你掌握了几种?

Java 程序员 后端

Java基础 - 多态,抽象类,接口,linux源码学习

Java 程序员 后端

Java 调试技术 JPDA 架构解读,图文详解

Java 程序员 后端

JavaOOP面试题48题(含答案),大厂Java高级多套面试专题整理集合

Java 程序员 后端

JavaWeb快速入门--Tomcat,java高级特性面试

Java 程序员 后端

Java之StringUtils的常用方法,java整体项目架构图

Java 程序员 后端

京东这样用 Flink:适应业务的才是最好的_QCon+_Alice_InfoQ精选文章