【监控】数据平台运营实战之如何打造应用级别的监控系统
本文介绍了如何设计监控系统的客户端包、后端服务以及存储的解决方案。
传统IT公司可能最核心的应用就是Web服务器和各种Web应用。得益于开源系统以及大数据理念的盛行,大大小小的公司逐渐形成了数据采集、存储、计算一体化的相似而又不同的架构。而在这些架构之上,我们可以丰富自己主营业务或者产品线的各种应用,或者说,技术团队有了这样的平台,我们可以更加方便的搭建各种应用程序。以前我们仅仅比较关注基础设置层面的监控(比如:服务器的load、内存使用、磁盘使用、CPU使用,像ganglia,zenoss就有这样的监控功能),在这些趋势的影响下,除了基础设施之外,我们不得不着眼于平台层面和各种应用的监控。
有人说,以前我们也关注Web应用的QPS、PV等等,但那个时候监控更多的是自己单独实现的几个指标统计。今天我们换个角度去审视监控的问题:现在我们平台上运行着各种各样的应用,这些应用有自己的运维或者开发人员,平台运维与应用运维需要各司其职,那么问题来了:如何保证他们可以很好的协作,又不互相干扰?
上面的图就表示了平台和应用分工的状态。试想一下,如果应用开发者的程序出现Bug或者有性能问题就跑过来问平台运维人员:“是不是你的服务端没数据?”,“是不是服务器挂了?”,于是平台运维人员就要费劲的查明真相,那必定会浪费大家的时间。所以最好的方式就是让双方都能了解自己负责的程序的状态如何,那么监控就是最好的方式,确切的说,是一个支持多用户的监控平台。
那么,搞清楚需求,就可以开工了。需要从何搞起呢?我先根据自己的经验列个清单,不全的各位帮我补充。
1. 监控数据的模型 2. 采集监控数据 3. 存储监控数据 4. 展示监控数据
我们先一步一步来,根据需求,需要什么信息(监控数据模型),然后在去实现如何获取这些数据(采集),之后就是存储,数据到手后,不管你是报表也好,曲线也好,实时预警,离线分析其实都不是问题。步步为营,且听我细细道来。
监控数据的模型
首先要考虑面向什么?是面向应用,还是面向用户?现在企业里离职率那么高,而且工作都是以负责的应用为准的,并且我们YY以后监控平台做大做强对外开放,那么还是面向应用吧!(一个人当五个人用的挨踢狗团队除外!因为一个人负责那么多应用了就只用面向人设计就行了,不然每个应用都要记住一些信息,自己看的累。。哈哈,大家不要介意,这是自黑!)。OK,面向应用去设计这条路很对,可以避免很多问题。那么,如果对于一个应用来说,它需要监控什么呢?试想一下,应用监控其实分了不同的角度,比如:我要监控它的性能负载,也要监控它的数据量是否有丢失,这实际上在描述两个不同的关注角度。也就是说,一个应用分了多个监控场景,为什么要这么区分呢?答:为了以后展示起来更容易理解,而且监控指标的扩展更加方便。那么,还需要什么?想象一下,其实监控数据的本质是日志,我们以前排查问题就是看日志的。日志的基本行为就是:追加 三元组(时间,地点,事件)。所以,我们把监控数据看做是一个日志文件,他的字段如下:
appID: 应用的唯一标识
sceneID:场景ID,应用下面的唯一标识
timestamp:时间戳
location:汇报该指标所在的位置,可以是一个ip,也可以是一个ip+端口,也可以是用户自定义的一种特定标识
dimValue:具体指标名称,比如在负载场景下,具体指标就有:QPS,刷磁盘速率,Buffer大小等等
kpiValue:对应指标的值,可以是速率类型的,也可以是百分比类型的,也可以是个绝对值大小
如此一来,你就可以根据这些标准格式的日志数据去排除应用程序出现的问题,当然了,如果你采集的足够实时,完全可以做到预警。当然,如何展示数据,决定了你工作效率的高低,图形曲线或者饼图可能是非常好的选择,性能指标的走势看起来像股市曲线一样爽,当然不能YY太早,数据展示还没有具体分析,我将会在下文提到。
采集监控数据
我们搞清楚需要什么数据了,但数据怎么来呢?采集,是张口就来的方案,最好的方式就是不动一行代码就可以抓取想要的数据。你当计算机是你肚子里的蛔虫呢?那不可能。不入侵原来应用的代码,似乎是所有开发人员的共同需求。但是既然通用就必须要有个标准,摆在你面前的只有两条路:要么改代码,要么改代码。你此时心中一定万匹草泥马奔腾,但事实就是如此:要么改代码标准化本地log的规范,使得抓取程序可以读取完成统计和计数的功能;要么入侵代码,使用简单的API直接调用即可完成统计和汇报数据。你选择哪个?后者可以保证应用开发人员改动最小的前提下完成更多的功能。不明白吗?我给你讲一下具体怎么实现。
具体的效果就是如上图所示,App1使用了监控客户端包之后,那么它会自动的汇报一个sce_load(负载监控场景)中的qps(代表近一分钟内平均访问次数)指标,100机器上测得的是9120,即每秒会有9120次访问。“QPS”完全是用户自己取得名字,他知道其含义,而监控的客户端包仅仅负责汇报数据。
那么看到这里,你一定会有很多疑问:9120是什么含义?如何让它能计算出这个数据?汇报时隔一段时间汇报还是一直在汇报?OK,我们先理一下,首先,我们既然入侵了代码,那么这个监控客户端包就要老实一点,我们的经验是一分钟汇报一次即可。而且,计数的代价要非常低,具体实现就应该是本地计数而已,汇报时需要异步的去读取本地内存中的统计数据,然后在一个deamon线程里面去发送数据。
数据的含义也需要标准化,其实开源的java metrics(或者了解一下jmx)给我们提供了非常好的方案,它的数据统计类型仅有五种:速率、计数、绝对值、时间分布、数值分布。分别举例说明:速率即使某种方法调用次数,计数就是累加呗,绝对值即是队列大小,时间分布即是方法调用耗时所占总调用次数某个百分比的都在多少以上。。这个有些绕,比如吧50%以上调用都在700毫秒之下,那么xxxx_p50 = 0.7,xxxx是你自己取得指标名称。
另外,作为一个包而言,而且要非常的易用:
MonitorClient client = MonitorClient.getInst("App1","sce_load");
public void yourVisitFunc() {
client.someKindOfStat("qps")
.....
......
}
只要在你的方法中嵌入了这一行client.someKindOfStat("qps"),那么上面的统计均可实现。具体统计方法,你要理解一下java metrics的客户端使用才能理解。剩下的乱七八糟的就是API封装啊,依赖包避免冲突啊,就像log4j这种你要搞成provided。
存储监控数据
Table Rolling示意图
上文提到,我们的监控数据实际上就是日志。日志是怎么定义,其实就是append,仅此而已。并且通过设计它的数据模型我们知道,这是一张包含了六个字段的大表且非稀疏表。另外它的存储时效可能有一些要求,因为我们会要求分析历史数据。查询一般需要带上5个字段(kpiValue字段除外)。现在的选型其实没有什么特别,用MySQL可以,用Phoenix也可以。MySQL的话需要按照时间分表,因为一张表太大了查询写入都会变慢。Phoenix就没这个问题了,它基于Hbase,并且支持SQL语言,是非常理想的选型。然而我们如何清理数据呢?这里需要指出一个问题,大量的删除HBase的数据会导致他在一次Major compaction的时候IO拥堵,因为他的删除只是做了墓碑标记,都是统一做合并时才彻底删掉的。对于这个问题我多介绍一下经验,可以从日志结构的特点去设计存储结构。那就是做Table rolling,顾名思义,table就像日志文件一样,随着时间rolling起来。为什么要这么做呢?是因为我们批量删除的数据具备时间特征,也就是说在Table Rolling的设计下,我们可以巧妙的删除以前的一整张表,而不是删除一张大表中的某些数据,这样做Major Compaction的时候就不会影响当前追加表的性能了。理解Table Rolling的设计前提是理解日志结构。
严谨的你肯定觉得缺点什么,因为直接让所有的客户端直接写入HBase或者MySQL的架构是有问题的。YY一下,如果我们的平台应用成千上万,这么多的Hbase客户端连接一定会搞垮整个集群。所以,需要一个接收数据的服务端去完成任务,那就是Nginx+Webserver。定义好监控数据的报文协议,比如定义一个嵌套好的Json,Client异步的批量发送Json,然后通过Nginx转发给无状态的Webservers,Webserver负责解析并入库。基本的优化思路就这些了,负载均衡,批量写入等等,技能无他。
存储这块总结起来两点:理解日志的含义,适当加一些中间件。
展示监控数据
最最决定其意义的环节到来了,那就是如何将这些有意义的数据呈现给用户呢?总结起来:可交互的UI+带有分析的报表。
上面的图片即显示了一个交互式查询的线框。上面有时间范围的选取、按照指标名称还是按照主机名称的分组、选择具体的指标(维度)、选择具体的主机等等,这样,用户可以查看其关注指标在时间上的走势。这个图其实作用非常大,开发者所关注应用的某个方法调用频次,方法耗时,以及Buff队列大小等等都可以观看,另外,通过两条曲线比较可以做到核对数据的功效。总之,各种应用场景待挖掘。在此推荐一下highcharts,非常好用的控件,构造曲线图真的是分分钟。
另外一个比较值得关注的数据产出是表报,你可以给你的Boss看,也可以利用报表去了解峰值出现时段等等。只要你能写出来的SQL,定期运行就有优质的产出。
另外值得一提的是,监控平台的数据是非常有价值的,你完全可以定义好Server API开放给平台用户,让他们自己去定制报表。这样,省的他们整天来找你提需求。作为一个平台运维开发人员,不需要那么拼的~
系统架构图
最后回过头来总结一下,平台应用程序利用监控的Client包实现了应用级别的监控,静默的吧统计信息发送到Webserver,Webserver入库之后,用户可以通过交互式查询和离线分析的方式去了解自己的应用状况,用户也可以通过监控数据的API服务接口定制自己的产出报表。这样一个监控系统就搞定了,当然了,面向App的设计需要你维护一些用户与App的关联信息。建议你好好考虑一下ACL设计,如果你设计的足够好,有助于你将监控平台化,如果你不太明白,那么就看看我后续的文章吧。