app服务治理(二):大数据下的异常定位

导语:系列一搞定异常发现后,就轮到异常定位了。所谓异常定位,就是找到异常发生处,比如异常是发生在哪个模块或哪行代码。目前笔者在FinTech领域供职,身临BigData场景,本文将介绍BigData下app异常定位的设计思路和解决方案,以及业内比较、如何开放、系统能力评估。

1、技术难点:跳入大数据的坑

单个异常的定位并不难,比如通过app端回传的异常栈一眼就能定位crash在哪。但笔者在FinTech领域供职,所在部门要接入最多上千个金融类app,和所有BigData场景一样,本来看似简单的问题将变得极端复杂,难点包括:

  • 数据维度/灵活性:一开始,我们设计以app模块为服务治理单元,不久便发现各个app对异常定位的要求并不相同,上至整个app,下至单个页面元素,比如A要求模块级别的定位,B要求页面级别的定位,这要求对上千家app各种维度的数据进行分析。

  • 实效性:金融行业有很高的止损诉求(毕竟关系到钱),很多核心服务的治理是要实时的,尤其实时发现和定位异常,而在高并发大流量场景下做实时具有很大挑战性。

实时一般指低延迟,是个相对的概念。由于异步架构和网络开销,本文系统核心的实时能力在s级,这在我们业务范围内已经足够。当然,对于少部分延迟要求极低的服务,可以单独做到更低延迟,但过于定制化,不是本文重点

  • 跨平台:为了实现app服务治理,要采集分析app端和服务端的数据,里面会包含各种DSL定义的接口数据

需要强调一点,我们优先解决的是规模问题,至于BigData领域的弹性计算,全权交给了公司的云服务。

2、设计思路:单调到灵活

近几个月,我们经历了3个阶段。

阶段1:单维度模式。最初,以app模块为服务治理单元,对数据源的每条数据流格式要求很简单,只需包含模块名和该模块数据,我们称之为单维度模式。这种模式简单,但单调,因为只能分析以模块为维度的数据。

阶段2:多维度模式。不久,我们发现服务治理单元远不止app模块,理论上所有维度都能充当治理单元,这就要求兼容各个维度甚至是服务端api维度的数据。为此,我们调整了数据流格式,包含4个必选项appIdosappVersiondataType和其他可选项,其中data可用来传递任意数据项,实现数据维度的无限扩展,我们称之为多维度模式。该阶段最关键是制定了一套通用数据源格式标准,相比于单维度模式,这套标准能轻松扩展到任意类型的异常定位,进而扩展到任意维度的服务治理。

  * @param appId app唯一标示,必选
  * @param os 操作系统,必选
  * @param appVersion app版本号,必选
  * @param dataType 数据类型,对应策略名,用来指定使用哪个策略,必选
  * @param osVersion 操作系统版本号,可选
  * @param deviceId 设备号,可选
  * @param deviceName 设备名,可选
  * @param channel 渠道号,可选
  * @param location 位置,可选
  * @param ip ip号码,可选
  * @param mobilePhone 手机号,可选
  * @param networkEnv 网络环境类型,可选
  * @param telecomOperator 基础运营商名称,可选
  * @param time 数据发生时间,后台可根据数据类型的不同,选择性信任此参数,可选
  * @param userAgent 用户代理类型UA,可选
  * @param screenSize 屏幕大小,可选
  * @param data 数据详情,可选

阶段3:DSL。多维度模式只是统一了数据源,我们还需要对原始数据进行分析,转化成知识,这些知识告诉我们什么时候出了异常(异常发现)、异常在哪里(异常定位)。面对多维度数据多场景化,系统的分析能力必须足够灵活,能覆盖任意异常的分析,归根结底,就是要实现条件可定义条件可定义的意思是针对任意类型异常,都能设置一个条件,当数据流满足该条件时,就意味着此类型异常发生并能进行定位。虽然策略平台早在单维度模式阶段就能通过配置策略来定义条件,但比较粗糙,为了更灵活定义条件,策略平台引入了DSL对条件进行表达。

为何叫条件可定义而非异常可定义,是因为策略平台不单单用于异常发现和定位,还能用于数据统计,即能够定义当满足何种条件时就统计何种数据。而且,不单能统计移动端(类似Google Analytics、TalkingData),还可以统计服务端(比如api统计)

3、解决方案:SQL on jstorm

3.1、具体异常定位实例

假设有一个iOS应用,应用ID为100,要为该app的一个abc模块设置crash监控,要求如果一个小时内crash数目>100,就向abc维护者发送监控报警邮件。

我们的系统是如何定义一条策略来表达上面的crash监控需求?

图1:crash监控策略实例

如上图所示,我们先配置3个知识条件,表示当数据流符合appId=100、os=ios、module=abc时,将产生一个知识数据,这个知识数据就是应用的abc模块在最近一小时内累积的crash个数。每来一个符合这3个知识条件的原始数据流,该知识数据就变化一次,即crash个数就增1。该知识数据(crash个数)将在redis中保留1个小时。接着,我们又配置了1个应用条件,表示一旦知识数据符合该条件(crash个数>100),则触发应用策略(发送报警邮件)。除了可以设置触发何种应用策略外,我们还能设置符合应用条件时是否将知识数据进行持久化,这可用来做数据统计,用在本节实例身上,就是可以统计abc模块每小时的crash个数。

总结起来,配置一个策略其实主要就是配置一系列条件,这个过程分为两部分:1)先配置N个知识条件,当实时数据流满足这N个条件,就产生相应的知识数据;2)再配置1个应用条件,当知识数据满足该条件,则启动相应的应用策略或持久化。

3.2、整体架构

本节,我们对策略平台整体架构做一个讲解。

图2:策略平台架构图

首先,使用者要在策略平台配置策略,包括配置N个知识条件和1个应用条件

接着,策略平台把知识条件转成一条sql。如上文所述,我们使用DSL来表达条件,而常见的DSL或结构化格式包括sql、json、xml等,我们最终选择sql,理由见下文。然后,将策略的所有配置项存入mongoDB,除了知识条件sql和应用条件外,其他配置项还包括策略名、描述、知识缓存时间等基本信息。

一旦有数据产生,数据源需按照标准格式把数据传给策略平台,即必须包含appIdosappVersiondataTypedataType是策略名,用来指定本次数据使用哪个策略来处理。数据流先到消息队列排队,再由jstorm异步拉取。对于那些延迟要求极低的核心服务,数据源的数据将直达jstorm,不在消息队列排队。

jstorm拉取到数据流后,SQL-like引擎先根据dataType取出对应的策略,解析策略中的sql,得到程序可识别的结构化知识条件,再把策略和数据流传给第2个bolt。第2个bolt中,知识分析模块分析数据流,如果数据流符合知识条件,则产生相应的知识数据,然后使用inc或set命令把新的知识数据存入redis,并把新知识数据传给第3个bolt。第3个bolt中,应用分析模块对新知识数据进行分析,如果知识数据符合策略中的应用条件,则触发应用策略或知识数据持久化。

为了区别于狭义上的数据库sql,这里用了SQL-like

如果知识数据设置为可持久化,则需要定时将该知识数据从redis中不断同步进mongoDB。如果没有定时同步,只依靠数据流来触发持久化,一旦redis重启或redis过期时间到来之前没有数据流,知识数据将会丢失

3.3、系统核心

策略平台的核心支撑技术是sql on jstorm,本质上是一种SQL-like引擎(或QueryEngine)+计算框架组合,这样的组合业内并不陌生,比如hive on spark/hadoop、Greenplum等。

在大数据领域,计算框架基本算是标配,它们可以充分利用集群资源提升系统的计算能力,虽然单机性能有所损耗。对计算框架的选型,由于实时性要求以及社区活跃度,我们选择了流式计算框架jstorm。

SQL-like引擎最大作用是提供通用简单的sql语法,完成复杂查询和数据分析,一般用于数据仓库。业内有不少成熟的SQL-like引擎和工具,比如hive hql、spark sql 、wing等,但策略平台的特殊性,接入现有工具的改造成本太大,于是我们定制化了自己的轻量级SQL-like引擎。

有人说知识条件并不复杂,用简单的json就能表达,无需sql,更没必要单独做了一个SQL-like引擎,而我们之所以这么做,理由包括:

  • sql具有更直接明了的查询表达能力,学习成本也低,还能做查询优化
  • SQL-like在大数据领域很普遍,如果我们的SQL-like引擎无法适应未来的发展,可以小成本迁移业内成熟方案
  • 作为一个独立的无状态组件,升级和扩容缩容的风险变小
  • 基于开源库解析sql,开发成本不大

SQL-like引擎的设计借鉴了数据仓库概念,比如知识条件相当于维度(Dimention)、知识相当于事实(Fact)。我们支持的sql语法如下:

select 知识类型 from 策略名 where 知识条件

// 支持的知识类型包括不限于:
// 数据流中任意一个field:语法是field,可用于慢请求定位等
// 总数:语法是count(),可用于crash定位、流量控制、pv统计等
// 指定field的累加和:语法是sum(field),可用于累积流量统计等

// 拿3.1实例来说,就是select count() from crashMonitor where appId=100 and os=ios and module=abc

SQL-like引擎依赖JSqlParser完成词法分析、语法分析、ast树生成,对于一条简单sql,JSqlParser大概耗时30ms,为了提升性能,可以将解析好的sql条件存入local缓存。SQL-like引擎定制化了自己的逻辑查询计划和物理查询计划,未来再展开讲。

4、业内比较

图3:典型数据流图,来自知乎

Sensors Data创始人对典型的数据流做了个总结,如图3。如果我们把持久化数据进行可视化,就和图3差不多了,这解释了我们和业内的相似之处,那区别在哪?

  • 目标不同:我们要实现app服务治理,业内没有成熟方案
  • 手段不同:app服务治理分为知识和应用两个阶段。知识阶段对增量数据(实时数据流)和存量数据(redis中的知识数据)做整合分析,而业内一般对存量数据(全量原始数据)做分析,也正由于知识数据量远比原始数据量小,因此可以做到s级低延迟。而应用阶段依赖知识数据做任意应用,比如异常解决,应用和业务强相关,业务在业内不一样,应用也就不一样。

整个过程中,分析(或训练)的数据都拥有分类标记,分析结果是对异常的预测,算是一种简单的有监督机器学习。

不过,如果未来需要用到离线的原始数据做治理,如何解决?这已经涉及到传统的数据仓库OLAP甚至是data mining了,需求极度灵活,往往要用到任意原始数据项和任意时间点的数据。但我们目前更关注实时治理而非事后离线分析,况且原始数据存储还有容量问题,要考虑引入Protobuf压缩等方案,因此只是暂时缓存了3个月的原始数据,以备不时之需。

5、如何开放

虽然开放和异常定位没有直接关系,但app服务治理的使用者是上千个金融类app的维护者,所以一开始设计就要考虑如何开放,实现Strategy-as-a-Service。要实现开放,以下事情很重要。

  • 接入数据:提供统一接口,使用者按照标准格式传递数据到策略平台
  • 配置策略:提供统一的操作页面
  • 反馈:提供统一的可视化图表,查看持久化数据和应用策略命中情况

6、系统能力评估

首先,套用CAP原理来评估,即一致性和高可用间的权衡。一般来说,有状态组件(比如redis和mongodb)是不一致问题之源,从图2得知,知识数据要从redis向mongoDB持久化,只能由知识分析模块或定时任务触发,而图4场景中redis和mongoDB会有一段时间的不一致,我们无法做到强一致性,只能通过定时任务保证最终一致性,但定时任务会使很多数据在同一时间从redis中清除和写mongoDB,降低了可用性。然而,为了追求某些场景的效率又偏向了可用性,比如我们将把sql解析结果缓存本地cache,修改sql后要同步所有机器清除本地cache,这里容忍同步期间的不一致。此外可用性方面,redis和mongDB都主从备,纳入HA(High available)系统,仅jstorm Nimbus是单点。

图4:redis和mongoDB数据不一致示例

接着是性能。先是消息队列中间件,一般考察TPS。通过Jason's Blog看到,kafka在3台4核虚拟机broker下,如果数据流传递了策略平台所有数据项,即按100字节算,将达到330w records/s和322MB/s,而redis pub/sub benchmark表明单机tps在几十万。

再来分析一下jstorm内组件的性能,重点考察TRT。假设命中的策略只设置了一个知识条件,按图2的数据流,一次数据流请求最多包含apout和bolt间3次网络消耗、3个bolt的逻辑处理耗时、读写mongoDB各1次、读写redis各1次、1次解析sql、1次http/dubbo应用请求,大概50~200ms。

事实上,生产环境的情况更复杂,因为可能不会触发写mongoDB和http/dubbo请求、一个策略包含多个知识条件等等,更详实的压测结果以后有机会再写。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,600评论 18 139
  • 导语:SOA(Service-Oriented Architecture,面向服务的体系结构)服务治理已经提出多年...
    star24阅读 1,732评论 3 5
  • 人生中第一次吃汉堡是初一,暑假的时候去小姑家。那几天弟弟经常跟小姑念叨要吃汉堡,但是小姑姑一直没答应。我心想,哦,...
    吴大仁阅读 524评论 0 0
  • 藏在家里许久的涂色本韩版秘密花园,一盒彩色铅笔,涂色一下午,趁最近发掘点艺术细胞,缓解压力,放松心情,竟为一副美腻...
    Ylibin阅读 136评论 0 0
  • 所谓横向领导力是在同等职位级别的情况下,如何影响同事,实现高效合作。不止适用于职场也适用于生活中影响家人跟朋友。 ...
    翠霞_0256阅读 193评论 0 0