微服务治理在接口服务监控预警和心跳检测中引入Flink思考
今天重点是谈下开源流处理框架Flink的使用场景,而实际的问题背景则是在SOA和微服务治理中,基于原有的服务监控预计,服务心跳检测等场景驱动,有引入该框架的必要性。从接口服务监控预警问题谈起
在前面谈服务治理和监控预警的文章中谈到过,接口服务的监控预警主要是根据服务运行次数,时长,异常和失败数量等进行阈值的设置,当超过这个阈值则进行预警。
在整个规则配置里面有一个关键内容,即时间窗口。
也就是说我们需要分析的是单位时间内的服务运行次数,平均运行时长,错误次数等。这个单位时间本身又可以灵活设置,可以是30秒,也可以是1分钟,5分钟。
在我们原来的实现方式中,我们是如何做呢?
即首先是将服务运行实例数据写入到数据库进行持久化存储,然后再单独开一个定时处理任务,对新增的实例数据进行统计计算,进行出Group by后的统计数据值。再形成一个中间统计结果表。由于这种方式很难做到实时,只能够是偏批处理的方式,因此但是时间间隔一般只能够做到1分钟进行批处理一次。
简单来说整个处理过程是:实时流数据=》持久化入库-》单独Job统计计算-》得出规则结果。这个一方面是导致较大的时延,一方面是引起更大的内存消耗。
而我们希望的方式是什么呢?
即在获取到服务实例运行数据后,实例数据的入库和规则的计算两者是并行进行的,即一方面不影响服务实例入库,一方面又能够拿到实例数据流后,实时基于时间窗口或周期进行计算,得出最终的统计结果并触发告警预警规则。
也就是实例日志在入库前,我们已经基于流处理的方式在内存中完成了该有的统计分析和计算过程,而不是等实例持久化后再查询出来数据进行统计分析。
这个实际在类似早期的Storm大数据流处理框架中本身就能够完成类似的事情。但是这个场景有一个关键点就是流处理+时间周期,这个就有点类似于流处理+批处理的结合方式。
如果时间周期是到秒足够小,本身就变成了完全的流处理方式,最小时延下完成实时统计处理。但是如果时间周期较长,比如5分钟,10分钟,我们又希望是偏批处理方式,以获取更大的吞吐量。
而Flink本身更好地兼容了这两种模式。Apache Flink流处理框架概述
Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。
任何类型所有数据都可以形成一种事件流。信用卡交易、传感器测量、机器日志、网站或移动应用程序上的用户交互记录,所有这些数据都形成一种流。
数据可以被作为无界或者有界流来处理。
无界流有定义流的开始,但没有定义流的结束。它们会无休止地产生数据。无界流的数据必须持续处理,即数据被摄取后需要立刻处理。我们不能等到所有数据都到达再处理,因为输入是无限的,在任何时候输入都不会完成。处理无界数据通常要求以特定顺序摄取事件,例如事件发生的顺序,以便能够推断结果的完整性。
有界流有定义流的开始,也有定义流的结束。有界流可以在摄取所有数据后再进行计算。由于界流所有数据可以被排序,所以并不需要有序摄取。
这里的有界流正是前面谈到的批处理方式,当每个批的量或时间间隔足够小的时候本身就完全变成了流处理模式。Apache Flink 擅长处理无界和有界数据集 精确的时间控制和状态化使得 Flink 的运行时(runtime)能够运行任何处理无界流的应用。有界流则由一些专为固定大小的数据集特殊设计的算法和数据结构进行内部处理,产生了出色的性能。
对于Flink简单总结就是:Apache Flink是一个开源的分布式、高性能、高可用的流处理框架。主要有Java代码实现,支持scala和java API。支持实时流(stream)处理和批(batch)处理,批数据只是流数据的一个极限特例。Flink原生支持了迭代计算、内存管理和程序优化。
Apache Flink架构
从上图可以看到整个Flink架构仍然是分为三层,最底层是物理部署和存储层,中间是核心层重点是处理运行时的分布式流数据处理,最上面是API接口层。对于API接口本身又分为了数据流处理接口和数据集批处理API接口。
Runtime核心层
对于Runtime核心层如上图,可以看到其包括了资源管理,分布式任务调度和处理,状态管理,持久化存储等内容。实际里面的核心仍然是分布式任务处理和调度逻辑,这个本身是基于事件处理架构模式的,可以灵活进行作业的编排,组装和组合。
其次就是State状态管理,可以实现关键状态的管理,中间计算结果的缓存等。
API & Libraries 层
Flink提供了支持流式计算和批计算的接口,通过在此基础之上抽象出不同应用类型的组件库,比如:基于流式处理的CEP(复杂事件处理)、SQL & Table 库、基于批处理的FlinkML、Gelly(图处理库)等,API层包括DataStream API 和批计算的DataSetAPI,两者都提供给用户丰富的数据处理高级API,比如Map、FlatMap、KeyBy等,用户也可以通过ProcessFunction API直接操作状态和时间的底层数据。
具体工作机制和原理大家可以参考下这篇文章:
https://www.cnblogs.com/wh984763176/p/13680907.htmlFlink应用场景分析
Apache Flink 功能强大,支持开发和运行多种不同种类的应用程序。它的主要特性包括:批流一体化、精密的状态管理、事件时间支持以及精确一次的状态一致性保障等。Flink 不仅可以运行在包括 YARN、 Mesos、Kubernetes 在内的多种资源管理框架上,还支持在裸机集群上独立部署。在启用高可用选项的情况下,也不存在单点失效的问题。
对于Flink的应用场景,官方网站给出了主要包括三类场景。Event-driven Applications(事件驱动)、Data Analytics Applications(数据分析)、Data Pipeline Applications(管道式ETL)。下面进行初步分析如下:
事件驱动型应用
事件驱动型应用是一类具有状态的应用,它从一个或多个事件流提取数据,并根据到来的事件触发计算、状态更新或其他外部动作。事件驱动型应用是在计算存储分离的传统应用基础上进化而来。在传统架构中,应用需要读写远程事务型数据库。
相反,事件驱动型应用是基于状态化流处理来完成。在该设计中数据和计算不会分离,应用只需访问本地(内存或磁盘)即可获取数据。
在前面我已经谈到接口服务监控预警就是一个典型的例子。
其中每一次接口服务运行实例本身就是一个消息事件,传统的处理方式都是事件消息先持久化进入到数据库,然后再单独起一个Job进行逻辑规则计算,得出最终的计算结果。也就是常说的数据和计算两者是分离开的。
而更好的方式是在获取到事件流信息后,能够基于制定的规则实时的进行计算,得到你希望的中间结果信息,再进行事件消息的持久化入库处理。这两件事情在一个流处理管道中可以同时完成,计算和数据存储不分离。
简单来讲这种场景可以归结为:消息事件不断地产生,需要根据批量规则或时间窗口规则进行实时的逻辑处理和计算,同时在计算完成后又需要对消息事件进行持久化存储。
事件驱动的核心仍然是将采集到的数据,或消息事件先写入到消息中间件或消息队列,然后Flink再发起对消息队列中数据的消费,并进行内存实时统计计算,最终得出最终的结果。当然整个处理过程又足够灵活,比如可以将流处理规则分解为多个不同的任务或Job,并进行灵活的组合和编排。
典型的事件驱动类应用,包括欺诈检测(Fraud detection)、异常检测(Anomaly detection)、基于规则的告警(Rule-based alerting)、业务流程监控(Business process monitoring)、Web应用程序(社交网络)等。
而前面谈到的服务告警预警,心跳监控可以看到都适合该类场景。
数据分析类应用
数据分析任务需要从原始数据中提取有价值的信息和指标。传统的分析方式通常是利用批查询,或将事件记录下来并基于此有限数据集构建应用来完成。为了得到最新数据的分析结果,必须先将它们加入分析数据集并重新执行查询或运行应用,随后将结果写入存储系统或生成报告。
借助一些先进的流处理引擎,还可以实时地进行数据分析。和传统模式下读取有限数据集不同,流式查询或应用会接入实时事件流,并随着事件消费持续产生和更新结果。这些结果数据可能会写入外部数据库系统或以内部状态的形式维护。仪表展示应用可以相应地从外部数据库读取数据或直接查询应用的内部状态。
如下图所示,Apache Flink 同时支持流式及批量分析应用。
还是拿SOA服务治理中的服务运行统计分析来举例。
在我们常规的服务运行统计分析中,往往是以5分钟为时间间隔,可以看到最近一个5分钟时间窗口实际的服务运行次数,时长,错误数等关键的统计指标数据。
以5分钟为单位的主要原因仍然是服务实例日志数据需要先写入到数据库持久存储,然后再有一个定时任务对服务实例数据进行统计计算,将统计结果数据写入到中间表。也就是服务运行统计实际查看的是中间表的统计结果数据。
在这种情况下数据和计算也是分离的,也无法做大实时或准实时的统计结果计算。
比如我们想做一个监控大屏,想实时看到最终的服务运行总量,错误量数据,那么这个时候只能够做到按分钟级这种定时的刷新效果,而很难做到实时的数据动态变化。要做到实时或低延迟的数据分析。就需要在采集到数据后实时计算,并将计算结果推送到前端显示。
对于类似热榜展示,实时在线交易额统计展示,监控大屏实时统计量刷新等都属于数据分析类场景。都可以采用Flink流处理方式来进行以减少数据的延迟。
数据管理类应用
提取-转换-加载(ETL)是一种在存储系统之间进行数据转换和迁移的常用方法。ETL 作业通常会周期性地触发,将数据从事务型数据库拷贝到分析型数据库或数据仓库。
数据管道和 ETL 作业的用途相似,都可以转换、丰富数据,并将其从某个存储系统移动到另一个系统。但数据管道是以持续流通模式运行,而非周期性触发。因此它支持从一个不断生成数据的源头读取记录,并将它们以低延迟移动到终点。
例如:数据管道可以用来监控文件系统目录中的新文件,并将其数据写入事件日志;另一个应用可能会将事件流物化到数据库或增量构建和优化查询索引。
下图描述了周期性 ETL 作业和持续数据管道的差异。
可以看到,对于采集到的数据加工,转换,清洗处理等都可以编排到实时数据处理管道中。即当获取到数据后,在内存中就对数据进行处理,最终将处理结果进行持久化即可。
数据管道本身不仅仅需要支持传统的ETL数据库SQL接口的集成和适配,同时也需要支持类似文件采集,HDFS库采集,消息中间件数据采集等多种大数据采集和适配模式。
对于ETL数据集成,当前为了简化过程和提升效率更多都采用的ELT模式,即先采集数据完成到目标端的装载处理,然后在目标端数据库进行相关的数据清洗,裁剪,整合统计操作。那么在这种场景下就存在一个关键问题,即:
我们采集的一个大批量数据,但是最终我们仅仅需要少部分需要的数据进行持久化入库,如果按照ELT的思路那么就带来明显的延迟,计算,存储能力消耗等。
比如采集大量的日志文件数据,但是仅仅需要解析出里面的异常数据进行入库,或者说大量的实例调用信息,只需要将统计结果数据入库等。那么采用这种数据流处理方式即是最佳的一种方式。