Fork me on GitHub

网易严选实时计算平台建设实践

图片

分享嘉宾:王杰瑞 (前)网易 资深服务端研发
编辑整理:宋灵城
出品平台:DataFunTalk

导读: 网易严选作为一家品牌电商,对数据实时驱动业务有较高要求。在严选,实时计算被广泛应用在实时数仓、风控、业务监控等场景中。本文将分享网易严选实时计算平台的建设思路和实践,并介绍平台后续的一些发展规划。从如下几个方面展开:

  • 背景介绍
  • 实时任务SQL化
  • Flink服务化
  • 数据治理
  • 后续规划

01 背景介绍

1. 发展历程

网易严选是一家电商平台,我们的业务链路主要涉及商品采购,销售,物流以及售后等一系列服务,拥有非常丰富的数据业务使用场景,在很多业务决策上都需要用到实时的数据来进行分析,因此,平台本身对数据的时效性和准确性有很高的要求。

图片

从2017年开始,我们进行平台化的建设,在整个过程中,我们的发展历程如上图所示:

  • 2017年是平台化的开始与探索
  • 2018年6月,上线Streaming SQL功能
  • 2019年专注服务化的建设,并在年底落地Flink on K8s的部署
  • 2020年集中在平台治理体系的建设方面
  • 今年开始做一些批流融合方面的探索和建设

2. 平台现状

图片

目前,整个平台大概运行了5000多个任务,每天峰值流量可以达到每秒2000万左右,平台从数据采集到对外提供服务,整体延时在秒级别。在网易严选,实时计算覆盖的场景非常丰富,比如:实时大屏,实时风控算法,日志业务监控以及APM预警等基础服务方面的应用。

3. 平台架构

图片

上图是我们实时计算平台的整体架构图,最底层是数据的基建层,主要提供了kafka、pulsar等消息队列,Yarn、K8s等计算资源以及其他存储组件。

在数据基础架构层之上,我们做了一个服务化的抽象,主要是为了屏蔽Flink任务和底层基础设施的交互过程,以服务的形式开放给上层平台或第三方系统。

再往上是平台层,是应用开发的主要入口,我们向用户提供了开发运维等使用功能,以及监控报警等基础功能,同时我们也提供了元数据管理,血缘分析等任务治理方面的工具。

在平台层的基础上,我们基于实时计算构建了丰富的应用,比如ETL,数仓,风控等一系列数据方面的应用。

02 实时任务SQL化

在大数据领域,无论是实时计算还是离线计算,整体的发展趋势都是朝着SQL化的方向在演进。我们平台建设之初,用户需要使用java或者scala自行编写Flink任务jar包,托管到平台上运行。这种方式存在两个问题:一个是开发门槛相对较高,另一个问题是在任务调试和线上调优时非常困难。所以我们希望提供一个能开箱即用的开发环境,来降低用户使用实时计算的门槛。

图片

上图是Atom开发平台,是我们提供的FlinkSQL开发IDE,用户可以在这里完成整个任务的开发,调试以及上线等过程,并且Atom集成了统一元数据,UDF仓库以及版本控制等基础功能,能进一步提升用户开发SQL任务的效率。

SQL平台的设计思路主要围绕如下四个方面展开:

图片

1. 统一元数据管理

图片

在元数据管理方面,初期我们通过DDL语句将外部存储以表的形式映射到FlinkSQL中,这样做存在明显的缺点,一个是使用起来非常繁琐,另一个是应用之间服务无法复用。因此为了避免开发前的繁琐工作,我们对主流的存储(比如:kafka,Hbase等)做了全方位的打通,用户开发过程中不需要关心具体的消息格式问题,IDE会提供统一的格式解析插件来处理。

2. UDF管理

图片

在UDF方面,首先我们对FlinkSQL本身所欠缺但是很常用服务做了扩展,比如说Json解析,时间处理以及近似去重等。另外,我们提供了UDF仓库,类似于maven仓库,用户可以自由的去上传自定义的UDF,仓库会对这些UDF做统一的管理和复用,等它发布后,这些UDF就可以在不同开发人员之间共享。当一个任务需要引用某一个UDF后,平台会自动去完成资源的加载和UDF的注册。

3. 功能扩展

图片

  • 连接器扩展: 我们提供了比较丰富的Connector,比如mySQL,pgSQL,TiDB,ES等,能够支持各种场景。
  • 维表增强: 支持维表关联及维表数据缓存。
  • 窗口扩展: 定时触发窗口输出,优化窗口的延时。
  • DDL扩展: 扩展DDL的语义功能,支持set语句来自定义配置属性,支持自定义的时间属性,同时提供视图语句来简化SQL开发难度。

4. 任务提交与调试

图片

在任务提交和调试方面,目前我们采用将用户提交的SQL编译成JobGraph,然后提交到集群去运行,在这个过程中也会去加载任务所依赖的各种connector和UDF等一系列的资源。

另外,平台提供了调试模式来支持在线调试FlinkSQL任务,在调试模式下,平台会对SQL进行改写,然后实时拦截调试的输出结果,来让用户及时观察任务的运行结果,同时调试的过程中可以自定义的制定线上数据采样的时间段,使调试更加灵活与准确。

03 Flink服务化

服务化是为了简化我们对任务管理的复杂度,对于上层的应用或者整个平台来说,可以屏蔽掉Flink与底层资源的交互细节,上层的平台可直接通过 rest或者RPC与服务层进行交互来操作任务,比如控制任务的起停,状态监听或者观察checkpoint和savepoint等,同时还提供了任务失败自动恢复等机制。

图片

我们通过插件的方式来支持多版本的Flink 任务,不同的版本可以共存;平台也可以支持底层的计算资源的多样性,可以通过插拔的方式切换多个yarn或者K8s集群。

通过服务化的方式,我们就可以将整个实时计算的生产能力开放出去,不仅仅是供我们的平台使用,而是可以提供给其他服务使用,比如日志平台或者监控平台等,这些平台的实时计算需求,就可以直接通过服务化的接口统一处理。

1. 资源优化

图片

随着任务数越来越多,作为平台方就需要进一步考虑资源优化问题。在讲具体优化之前我们先对比下Flink常用的两种部署模式:

  • per-Job模式

    单个作业绑定一个cluster,优点是资源隔离性好,但缺点也很明显,会存在资源浪费情况。每个任务需要有独立的jobManager,对于资源需求小的任务,TaskManager资源不能被充分利用,可能会导致container资源分配粒度与任务需求不一致的情况。

  • session模式

    多个任务复用一个Flink cluster的jobManager和taskManager。优点是资源利用率高,但是缺点就是隔离性相对较差,任务间会互相影响,比如类加载问题。同时,同一个session中,不同任务请求资源的粒度还需保持一致。

图片

综合分析上面两种部署模式的优缺点后,我们做了一些改进措施。采用了基于session的一种新部署模式。通过提供任务资源策略和资源池的方式来提高session模式下的资源方式。我们抽象出一个资源策略的概念,即根据作业的类型,以及它的对资源申请的需求做的一个抽象,通过这个资源策略来划分不同的资源池。当提交一个任务时,平台会根据它所声明的资源策略来选择性的决定该任务应该分配到哪一个资源池的哪一个session中,这样分配一方面可以复用jobManager和taskManager的计算资源,另一方面可以保证在同一个session中,所运行的任务的资源申请粒度是一致的。所以在这种模式下,可以实现平台在任务的隔离性和资源利用率之间的相对平衡。

2. 云原生部署

图片

在服务化的过程中,我们还完成了任务云原生的部署方式。在早期平台任务都部署在Yarn集群上,因为一些历史原因,Yarn集群没有使用cgroup等方式做CPU的资源隔离,这常常出现同一机器上的不同任务CPU资源占用的情况。而且整个Yarn集群是基于物理机来部署的,当需要对集群资源做临时的扩容时就显得非常不方便,且周期很长。另外,整体的运维人力成本也比较高。所以我们考虑使用K8s来代替Yarn集群,K8s的主要优点是资源隔离相对彻底,而且支持快速的弹性扩缩容,这样就可以满足我们多类型任务的混合部署,从而提升计算资源的整体利用率。

图片

在网易严选,我们在2019年底,基于Flink1.6版本完成了Flink on k8s的落地。并且在2020年,完成Flink1.10版本的整合,目前平台任务的容器化部署覆盖率超过80%。同时根据业务需要,我们还做了一些自适应的扩展。具体扩展如下所示:

  • 支持通过Node Selector来按照标签去选择性调度任务,做到资源隔离
  • 引入ingress是来提供对外的rest服务
  • 增强对API Server连接抖动、网络异常的容忍度
  • 支持通过Sidecar进行日志收集,Service Mesh等
  • 优化Native内存泄漏问题
  • 支持基于Zookeeper的jobManager HA能力

04 数据治理

图片

如上图是网易严选在数据处理中的整体链路,通过分层的结构来支持数仓的需求。从图中可以看到整体链路比较长,且任务之间的依赖关系复杂,所以我们需要对整个数据体系进行全链路的治理。数据治理的目的就是为了保障数据能够高效稳定的产出,同时推进全链路的资源优化。

1. 任务监控

图片

在数据治理过程中,我们需要完善对任务处理情况的监控,比如像风控等业务,对任务的稳定性和时效性比较敏感,无法容忍任务长时间故障或者异常延迟等。Flink本身提供了丰富的metrics指标用来监控任务全生命周期的健康情况,但是当任务数量越来越多时,Flink metrics的体量也会非常大,我们经过调研和对比常用的时序数据库后,选择使用OpenTSDB来作为metrics的存储,同时通过加盐哈希的方式来分散存储和查询热点。另外,我们统一为各种连接器提供访问延迟、缓存命中等多项指标,同时将指标的粒度细化到算子级别,方便我们定位和排查问题。

2. 数据血缘追踪

图片

在数据治理中另一个重要的基础服务是对数据血缘的管理,Flink任务中SQL任务,我们通过对SQL做语法树的遍历来拿到它血缘情况,而针对用户自定义的jar任务,需要在生成JobGraph时获取它的DAG结构,然后通过反射机制来获取血缘的元数据。统一的血缘管理,可以清晰的获取到任务的上下游关系,方便问题的快速定位和排查。

3. 全链路数据治理

图片

依托我们提供的统一元数据、任务监控以及统一血缘管理这三个基础服务,我们就可以对数据做全链路治理。在数据治理中,我们主要从两个维度来考虑。

首先是表的维度,所谓表,在实时中大部分指kafka,而在离线中指hive等各种存储。依赖于全链路的数据,我们可以建立数据的访问模型,通过模型可以很好的识别表的冷热情况,然后针对不同的情况做一些分级的治理。比如在kafka这一块,我们会对一些热点表做资源分区的调整及扩容,而对一些无效的表,我们会自动的清除。

其次是任务的维度,依托对任务的全生命周期管理以及监控指标的聚合分析,通过智能诊断框架去自动识别任务的问题所在,比如任务延迟,数据倾斜、反压以及资源不足等,然后通过进一步的分析,对任务做资源的优化及调整。

通过全链路的数据治理,我们把任务的延迟控制在秒以内,提升了平台的整体稳定性。

05 后续规划

1. 流批一体探索

图片

在流批一体的探索过程中,目前我们初步完成了Iceberg数据湖的集成,接下来会进一步探索计算及存储层面的批流一体架构。

2. 作业智能诊断优化

图片

进一步强化作业智能诊断能力,引入作业管控服务,当诊断框架给出调优方案之后,通过作业管控服务自适应的对任务做具体的调优,从而减少人工的介入,提升作业整体的可用性。

06 精彩问答

Q:存在update情况下,Flinksink到下游输出时,如何实现幂等性?比如Flink写到Hbase如何实现幂等性?

A:FlinkSQL本身在retract模式或者upsert模式下,若下游存储存在主键,比如Hbase的rowKey,更新或者删除操作都是根据主键来实现,所以结果是具有幂等性的。若下游存储没有主键,比如kafka,就需要下游存储自身做幂等的操作,这种情况会更复杂。

Q:用户对调试功能需求高吗?其主要的实现思路是什么?

A:实际业务开发过程中,FlinkSQL通常会比较复杂,代码量比较大,所以很难一次性完整的写出来,所以调试功能的使用是非常高频的。无论是构造的数据还是采样线上的数据,我们在调试模式下需要及时的展现这段SQL的结果,方便用户来判断其SQL的逻辑是否达到自己想要的效果,实现思路大概是:对SQL任务source和sink做替换,对source,我们会实现Kafka采样的功能或使用用户上传的样例数据,对sink,我们会替换成webSocket输出或者文件输出,方便用户的查看。


本文地址:https://www.6aiq.com/article/1639438996585
本文版权归作者和AIQ共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出