共计 5612 个字符,预计需要花费 15 分钟才能阅读完成。
本文将为大家介绍 Apache Flink 在爱奇艺的生产与实践过程。你可以借此了解到爱奇艺引入 Apache Flink 的背景与挑战,以及平台构建化流程。主要内容如下:
- 爱奇艺在实时计算方面的的演化和遇到的一些挑战
- 爱奇艺使用 Flink 的 User Case
- 爱奇艺 Flink 平台化构建流程
- 爱奇艺在 Flink 上的改进
- 未来工作
爱奇艺简介
爱奇艺在 2010 年正式上线,于 2018 年 3 月份在纳斯达克上市。我们拥有规模庞大且高度活跃的用户基础,月活跃用户数 5.65 亿人,在在线视频领域名列第一。在移动端,爱奇艺月度总有效时长 59.08 亿小时,稳居中国 APP 榜第三名。
一、爱奇艺在实时计算方面的演化和遇到的一些挑战
1. 实时计算在爱奇艺的演化过程
实时计算是基于一些实时到达、速率不可控、到达次序独立不保证顺序、一经处理无法重放除非特意保存的无序时间序列的数据的在线计算。
因此,在实时计算中,会遇到数据乱序、数据延时、事件时间与处理时间不一致等问题。爱奇艺的峰值事件数达到 1100 万 / 秒,在正确性、容错、性能、延迟、吞吐量、扩展性等方面均遇到不小的挑战。
爱奇艺从 2013 年开始小规模使用 storm,部署了 3 个独立集群。在 2015 年,开始引入 Spark Streaming,部署在 YARN 上。在 2016 年,将 Spark Streaming 平台化,构建流计算平台,降低用户使用成本,之后流计算开始在爱奇艺大规模使用。在 2017 年,因为 Spark Streaming 的先天缺陷,引入 Flink,部署在独立集群和 YARN 上。在 2018 年,构建 Streaming SQL 与实时分析平台,进一步降低用户使用门槛。
2. 从 Spark Streaming 到 Apache Flink
爱奇艺主要使用的是 Spark Streaming 和 Flink 来进行流式计算。Spark Streaming 的实现非常简单,通过微批次将实时数据拆成一个个批处理任务,通过批处理的方式完成各个子 Batch。Spark Streaming 的 API 也非常简单灵活,既可以用 DStream 的 java/scala API,也可以使用 SQL 定义处理逻辑。但 Spark Streaming 受限于微批次处理模型,业务方需要完成一个真正意义上的实时计算会非常困难,比如基于数据事件时间、数据晚到后的处理,都得用户进行大量编程实现。爱奇艺这边大量使用 Spark Streaming 的场景往往都在于实时数据的采集落盘。
Apache Flink 框架的实时计算模型是基于 Dataflow Model 实现的,完全支持 Dataflow Model 的四个问题:What,支持定义 DAG 图;Where:定义各类窗口(固定窗口、滑动窗口和 Session 窗口);When:支持灵活定义计算触发时间;How:支持丰富的 Function 定义数据更新模式。和 Spark Streaming 一样,Flink 支持分层 API,支持 DataStream API,Process Function,SQL。Flink 最大特点在于其实时计算的正确性保证:Exactly once,原生支持事件时间,支持延时数据处理。由于 Flink 本身基于原生数据流计算,可以达到毫秒级低延时。
在爱奇艺实测下来,相比 Spark Streaming,Apache Flink 在相近的吞吐量上,有更低的延时,更好的实时计算表述能力,原生实时事件时间、延时数据处理等。
二、在爱奇艺使用 Flink 的一些案例
下面通过三个 Use Case 来介绍一下,爱奇艺具体是怎么使用 Flink 的,包括海量数据实时 ETL,实时风控,分布式调用链分析。
1. 海量数据实时 ETL
在爱奇艺这边所有用户在端上的任何行为都会发一条日志到 nginx 服务器上,总量超过千万 QPS。对于具体某个业务来说,他们后续做实时分析,只希望访问到业务自身的数据,于是这中间就涉及一个数据拆分的工作。
在引入 Flink 之前,最早的数据拆分逻辑是这样子的,在 Ngnix 机器上通过“tail -f /xxx/ngnix.log | grep “xxx””的方式,配置了无数条这样的规则,将这些不同的数据按照不同的规则,打到不同的业务 kafka 中。但这样的规则随着业务线的规模的扩大,这个 tail 进程越来越多,逐渐遇到了服务器性能瓶颈。
于是,我们就有了这样一个设想,希望通过实时流计算将数据拆分到各个业务 kafka。具体来说,就是 Nginx 上的全量数据,全量采集到一级 Kafka,通过实时 ETL 程序,按需将数据采集到各个业务 Kafka 中。当时,爱奇艺主的实时流计算基本均是基于 Spark Streaming 的,但考虑到 Spark Streaming 延迟相对来说比较高,爱奇艺从这个 case 展开开始推进 Apache Flink 的应用。
海量数据实时 ETL 的具体实现,主要有以下几个步骤:
- 解码:各个端的投递日志格式不统一,需要首先将各个端的日志按照各种解码方式解析成规范化的格式,这边选用的是 JSON
- 风控:实时拆分这边的数据都会过一下风控的规则,过滤掉很大一部分刷量日志。由于量级太高,如果将每条日志都过一下风控规则,延时会非常大。这边做了几个优化,首先,将用户数据通过 DeviceID 拆分,不同的 DeviceID 拆分到不同的 task manager 上,每个 task manager 用本地内存做一级缓存,将 redis 和 flink 部署在一起,用本地 redis 做二级缓存。最终的效果是,每秒 redis 访问降到了平均 4k,实时拆分的 P99 延时小于 500ms。
- 拆分:按照各个业务进行拆分
- 采样、再过滤:根据每个业务的拆分过程中根据用户的需求不同,有采样、再过滤等过程
2. 实时风控
防机器撞库盗号攻击是安全风控的一个常见需求,主要需求集中于事中和事后。在事中,进行超高频异常检测分析,过滤用户异常行为;在事后,生成 IP 和设备 ID 的黑名单,供各业务实时分析时进行防刷使用。
以下是两个使用 Flink 特性的案例:
- CEP:因为很多黑产用户是有固定的一些套路,比如刚注册的用户可能在短时间内会进行一两项操作,我们通过 CEP 模式匹配,过滤掉那些有固定套路的黑产行为
- 多窗口聚合:风控这边会有一些需求,它需要在不同的一些时间窗口,有些时间窗口要求比较苛刻,可能是需要在一秒内或亚秒内去看一下某个用户有多少次访问,然后对他进行计数,计数的结果超过某些阈值就判断他是异常用户。通过 Flink 低延时且支持多窗口的特点,进行超高频的异常检测,比如对同一个用户在 1 秒内的请求进行计数,超过某个阈值的话就会被识别成黑产。
3. 分布式追踪系统
分布式调用链追踪系统,即全链路监控,每个公司基本都会有。在一个微服务架构当中,服务间的调用关系错综复杂,往往很难排查问题,识别性能性能瓶颈,这时候就需要分布式调用链追踪系统了。
上图是一个调用链的追踪拓扑图,每个点是一个具体的一个应用,就是具体经过哪个应用,每条边是说明这个应用到下一个应用当中耗时了多久。
除了宏观分析外,业务还想去看具体某一条日志的分析,具体某一次调用它是哪里慢了,哪里快了?所以,调用链还有另外一个需求,就是对于具体某次调用,想看一下它的具体耗时。
系统简单架构如上图,上半部分偏重于埋点,下半部分偏于分析。埋点简单来讲,就是通过客户端 SDK 埋点以及 Agent 采集,将系统调用日志全部打到 Kafka 中,我们通过 Flink 对他们进行各类分析。对于统计类的分析,就是通过 Flink 计算存储到 HBase 当中,提供一些监控报警、调用链拓普查询等这种分析。针对这类需求,我们运用了 Flink 的多窗口聚合的特性,通过一分钟或者多分钟的窗口,从茫茫日志中寻找哪条是实际的调用链,构建 APP 各个应用的拓扑调用关系,第二级是基于第一级分析的一个结果,分析出那个拓普图按各个窗口、各个不同的边去算每条边的平均耗时的统计。除此之外,我们还将通过 Flink 将原始数据打到 ES 里面供用户直接去查询。
三、Flink 平台化
1. 概览
接下来将主要介绍爱奇艺的大数据平台的构建。上图不限于 Flink,是大数据平台的整体架构图。在爱奇艺,存储层基本是基于 Hadoop 生态的,比如像 HDFS、HBase、Kudu 等;计算层,使用 YARN,支持 MapReduce、Spark、Flink、Hive、Impala 等这些引擎;数据开发层,主要是一些自研产品,批处理开发在爱奇艺有工作流开发,数据集成等。实时计算开发,有流计算开发、Streaming SQL、实时分析等平台工具可以使用。
接下来,我们将简单介绍爱奇艺实时计算与分析平台。
2. 实时计算平台
2.1 流任务平台
流任务平台是爱奇艺实时计算的底层平台,支持流任务的提交运行与管理。流任务平台支持 YARN, Mesos, Flink 独立集群等多种资源调度框架;支持 Storm, Spark Streaming, Flink, Streaming SQL 等计算任务的托管与运行。在功能上,我们支持用户直接打包程序上传部署流任务,也支持用户通过 Streaming SQL 工具编写 SQL 进行流计算开发。为了更好地对计算任务进行管理,流计算平台提供 JAR 包、函数管理,任务指标监控,以及资源审计功能。
2.2 Streaming SQL
无论对于 Spark Streaming 还是 Flink 来说,他们均有一个较好的 SQL 优化引擎,但均缺乏 DDL、DML 创建的语义。于是对于业务来说,均需要业务先编程定义 Source 以及 Sink,才可以使用 SQL 进行后续开发。
因此,爱奇艺自研的 Streaming SQL 定义了一套 DDL 和 DML 语法。其中,我们定义了 4 种表:
流表:定义了输入源是什么?具体的解码方式是什么?系统支持 Json 的解码方式,也支持用户自定义解码函数。
维度表:主要是静态表,支持 MySQL,主要是用于流表 Join 的。
临时表:和 Hive 的临时表类似,用户定义中间过程。
结果表:定义了具体输出的类型,输出的源是什么?怎么访问?这边的输出源支持,就是常见的比如 Kafka、MySQL、Kudu、ES、Druid、HBase 等这样一些分析型数据库。
为了更好地支持业务需求,StreamingSQL 默认也支持 IP 库相关的预定义函数,也支持用户自定义函数。
上图是一个 StreamingSQL 的应用 Case,将 P99,P50 耗时打印到 Console 中。
为了更好地支持业务使用 Streaming SQL,StreamingSQL 提供 Web IDE,提供代码高亮、关键词提示、语法检查、代码调试等功能。
3. 实时分析平台
实时分析平台,是爱奇艺基于 Druid 构建的分钟级延时的实时分析平台,支持通过 Web 向导配置,完成超大规模实时数据多维度的分析,并生成分钟级延时的可视化报表。支持的功能有,接入实时数据进行 OLAP 分析;制作实时报警;生产实时数据接口,配置监控报警等。
产品优势:
- 全向导配置:从实时数据到报表生成仅需向导配置即可
- 计算存储透明:无需管理大数据处理任务与数据存储
- 分钟级低延时: 从数据产生到报表展示只有 1 分钟延时
- 秒级查询:亚秒级返回分析报表
- 支持灵活变更需求:业务可灵活更改维度,重新上线即可生效
3.1 用户向导配置
实时分析平台,将整个分析流程抽象成数据接入,数据处理,模型配置和报表配置 4 个过程。其中,模型配置完全按照 OLAP 模型,要求实时数据符合星型模型,存在时间戳、指标、维度等字段。
3.2 数据处理配置
在数据处理层,实时分析平台提供向导配置页面,支持用户通过纯页面的方式就可以配置数据处理过程,这主要应对一些简单场景,针对部分连 SQL 都不熟悉的小白用户提供页面配置方案;初次之外,类似 StreamingSQL,实时分析也提供用户自定义 SQL 方式定义数据处理过程。
四、Flink 改进
在 Flink 平台化的时候,我们遇到了几个 Flink 的问题,分别对其进行了些改进。
1. 改进 – 优雅恢复 checkpoint
第一个改进是关于 checkpoint 的优雅恢复。这个问题的出发点是,业务希望使用 Spark Streaming 可以通过代码控制从哪个 checkpoint 恢复,但对于 Flink 来讲,业务没法通过代码控制 checkpoint 恢复点,需要手动指定检查点去恢复 checkpoint。于是,我们希望 Flink 可以像 Spark Streaming 一样,直接通过代码方式恢复 checkpoint。
针对这个问题,我们修改源码,在 Flink 任务启动时,从实际的路径当中找到他最新的一个 checkpoint,直接从那个 checkpoint 当中恢复,当然这个也是可以让用户选的,他如果还想用原生方式恢复也可以,但提供一个选项,它可以支持从最近的 checkpoint 恢复。
2. 改进 – Kafka Broker HA
第二个改进是关于 Kafka Broker HA 的一个问题,比如像 Kafka Broker 故障的时候,Kafka 还可以正常工作,但 Flink 程序往往会挂掉。针对这个问题,我们处理了 Flink 在 Kafka Broker 退出之后的 sockerTimeOutException,支持用户重试次数配置来解决这个问题。
五、Flink 未来工作
最后,介绍一下爱奇艺在 Apache Flink 的未来工作。目前 StreamingSQL 还只支持 Spark Streaming 和 Structured Streaming 引擎,后续很快会支持 Flink 引擎,大幅降低业务的 Flink 开发成本。随着 Flink 任务规模不断变大,我们将重点提升 Flink 在爱奇艺的成熟度,完善监控报警,增加资源审计流程(目前还仅对 Spark Streaming 进行资源审计)。另外,我们要研究下 Flink 1.6 的一些新特性,尝试下 Kafka 2.0,调研 Exactly once 方案;另外,我们将对 Flink 新版本进行一些尝试,推进批流统一。
本文作者:apache_flink
阅读原文
本文为云栖社区原创内容,未经允许不得转载。