网易严选实时计算平台建设实践
分享嘉宾:王杰瑞 (前)网易 资深服务端研发
编辑整理:宋灵城
出品平台: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时获取
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/geek/post/%E4%BA%92%E8%81%94%E7%BD%91/%E7%BD%91%E6%98%93%E4%B8%A5%E9%80%89%E5%AE%9E%E6%97%B6%E8%AE%A1%E7%AE%97%E5%B9%B3%E5%8F%B0%E5%BB%BA%E8%AE%BE%E5%AE%9E%E8%B7%B5/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com