经济高速发展的今天,我们处于信息大爆炸的时代。随着经济发展,信息借助互联网的力量在全球自由地流动,于是就催生了各种各样的服务平台和软件系统。
由于业务的多样性,这些平台和系统也变得异常的复杂。如何对其进行监控和维护是我们 IT 人需要面对的重要问题。就在这样一个纷繁复杂地环境下,监控系统粉墨登场了。

监控系统的功能
在 IT 运维过程中,常遇到这样的情况:
某个业务模块出现问题,运维人员并不知道,发现的时候问题已经很严重了。
系统出现瓶颈了,CPU 占用持续升高,内存不足,磁盘被写满;网络请求突增,超出网关承受的压力。
以上这些问题一旦发生,会对我们的业务产生巨大的影响。因此,每个公司或者 IT 团队都会针对此类情况建立自己的 IT 监控系统。

监控系统工作流程图
其功能包括:
对服务,系统,平台的运行状态实时监控
收集服务,系统,平台的运行信息
通过收集信息的分析结果,预知存在的故障风险,并采取行动
根据对风险的评估,进行故障预警
一旦发生故障,第一时间发出告警信息
通过监控数据,定位故障,协助生成解决方案
最终保证系统持续、稳定、安全运行
监控数据可视化,便于统计,按照一定周期导出、归档,用于数据分析和问题复盘
监控系统的分类
既然监控系统我们意义重大,针对不同场景把监控系统分为三类,分别是:
日志类
调用链类
度量类
日志类
通常我们在系统和业务级别上加入一些日志代码,记录一些日志信息,方便我们在发现问题的时候查找。
这些信息会与事件做相关,例如:用户登录,下订单,用户浏览某件商品,一小时以内的网关流量,用户平均响应时间等等。
这类以日志的记录和查询的解决方案比较多。比如 ELK 方案(Elasticsearch+Logstash+Kibana),使用ELK(Elasticsearch、Logstash、Kibana)+Kafka/Redis/RabbitMQ 来搭建一个日志系统。

ELK 结合 Redis/Kafka/RabbitMQ 实现日志类监控
程序内部通过 Spring AOP 记录日志,Beats 收集日志文件,然后用 Kafka/Redis/RabbitMQ 将其发送给 Logstash,Logstash 再将日志写入 Elasticsearch。
最后,使用 Kibana 将存放在 Elasticsearch 中的日志数据显示出来,形式可以是实时数据图表。
调用链类
对于服务较多的系统,特别是微服务系统。一次服务的调用有可能涉及到多个服务。A 调用 B,B 又要调用 C,好像一个链条一样,形成了服务调用链。
调用链就是记录一个请求经过所有服务的过程。请求从开始进入服务,经过不同的服务节点后,再返回给客户端,通过调用链参数来追踪全链路行为。从而知道请求在哪个环节出了故障,系统的瓶颈在哪儿。
调用链监控的实现原理如下:

Java 代码运行原理图
在介绍这种方式之前,我们先来复习一下 Java 代码运行的原理。通常我们会把 Java 源代码,通过“Java 编译器”编译成 Class 文件。再把这个 Class 的字节码文件装载到“类装载器”中进行字节码的验证。
最后,把验证过后的字节码发送到“Java 解释器”和“及时编译器”交给“Java 运行系统”运行。
Java 探针,字节码增强的方式就是利用 Java 代理,这个代理是运行方法之前的拦截器。
在 JVM 加载 Class 二进制文件的时候,利用 ASM 动态的修改加载的 Class 文件,在监控的方法前后添加需要监控的内容。
例如:添加计时语句,用于记录方法耗时。将方法耗时存入处理器,利用栈先特性(先进后出)处理方法调用顺序。
每当请求处理结束后,将耗时方法和入参 map 输出到文件中,然后根据 map 中相应参数,区分出耗时业务。
最后将相应耗时文件取下来,转化为 xml 格式并进行解析,通过浏览器将代码分层结构展示出来。

Java 探针工具原理图
备注:ASM 是一个 Java 字节码操纵框架,它可以动态生成类或者增强既有类的功能。
ASM 可以直接产生二进制 Class 文件,可以在类被载入 Java 虚拟机之前改变类行为。
Java Class 被存储在 .class文件里,文件拥有元数据来解析类中的元素:类名称、方法、属性以及 Java 字节码(指令)。
ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够生成新类。
②拦截请求
获取每次请求服务中的信息来实现跟踪的。这里以 Zipkin+Slueth 为例说明其原理。
Sleuth 提供链路追踪。由于一个请求会涉及到多个服务的互相调用,而这种调用往往成链式结构,经过多次层层调用以后请求才会返回。常常使用 Sleuth 追踪整个调用过程,方便理清服务间的调用关系。

Sleuth 服务调用追踪图例
每次请求都会生成一个 Trace ID,如上图所示这个 Trace ID 在整个 Request 和 Response 过程中都会保持一致,不论经过了多少个服务。这是为了方便记录一次调用的整个生命周期。
再看每次请求的时候都会有一个 Span ID,这里的 Span 是 Sleuth 服务跟踪的最小单元,每经过一个服务,每次 Request 和 Response 这个值都会有所不同,这是为了区分不同的调用动作。
针对每个调用的动作,Sleuth 都做了标示如下:
Server Received 是服务器接受,也就是服务端接受到请求的意思。
Client Sent 是客户端发送,也就是这个服务本身不提供响应,需要调用其他的服务提供该响应,所以这个时候是作为客户端发起请求的。
Server Sent 是服务端发送,看上图SERVICE 3 收到请求后,由于他是最终的服务提供者,所以作为服务端,他需要把请求发送给调用者。
Client Received 是客户端接受,作为发起调用的客户端接受到服务端返回的请求。
实际上 Sleuth 就是通过上述方式把每次请求记录一个统一的 Trace ID,每个请求的详细步骤记作 Span ID。
每次发起请求或者接受请求的状态分别记录成 Server Received,Client Sent,Server Sent,Client Received 四种状态来完成这个服务调用链路的跟踪的。

在调用服务的链路上每个被调用的服务节点都会通过 Parent ID 来记录发起调用服务的 Span ID,由于 Span ID 是唯一确认最小服务单元的,所以知道了 Parent 的 Span ID 也就知道了谁调用自己了。
度量类
实现了时序数据库(TimeSeriesData,TSD)的监控方案。实际上就是记录一串以时间为维度的数据,然后再通过聚合运算,查看指标数据和指标趋势。说白了,就是描述某个被测主体在一段时间内的测量值变化(度量)。
由于 IT 基础设施,运维监控和互联网监控的特性,这种方式被广泛应用。一般对时序数据进行建模分为三个部分,分别是:主体,时间点和测量值。
通过这个例子来看一下,时序数据库的数学模型,例如:需要监控服务器的 In/Out 平均流量:
整个监控的数据库称为“Metric”,它包含了所有监控的数据。类似关系型数据库中的 Table。
每条监控数据,称为“Point”,类似于关系型数据库中的 Row 的概念。
每个“Point”都会定义一个时间戳“Timestamp”,将其作为索引,表明数据采集的时间。
“Tag”作为维度列,表示监控数据的属性。
“Field”作为指标列,作为测量值,也就是测量的结果。

时序数据库数据模型图例
时序数据库的存储原理,关系型数据库存储采用的是 B tree,虽然降低了数据查询的磁盘寻道时间,但是无法解决大量数据写入时的磁盘效率。
由于监控系统的应用场景,经常会遇到大批量的数据写入,所以我们会选择 LSMtree(Log Structured Merge Tree)存储时序数据库。
LSMtree(Log Structured Merge Tree),从字面意义上理解,记录的数据按照日志结构(Log Structured)追加到系统中,然后通过合并树(Merge Tree)的方式将其合并。
来看一个 LevelDB 的例子,方便我们理解,LSM-tree 被分成三种文件:
接收写入请求的 memtable 文件(内存中)
不可修改的 immutable memtable 文件(内存中)
磁盘上的 SStable文件(Sorted String Table),有序字符串表,这个有序的字符串就是数据的key。SStable 一共有七层(L0 到 L6)。下一层的总大小限制是上一层的 10 倍。

LSMtree LevelDB 存储示意图
LSMtree 写入流程:
将数据追加到日志 WAL(Write Ahead Log)中,写入日志的目的是为了防止内存数据丢失,可以及时恢复。
把数据写到 memtable 中。
当 memtable 满了(超过一定阀值),就将这个 memtable 转入 immutable memtable 中,用新的 memtable 接收新的数据请求。
immutablememtable 一旦写满了, 就写入磁盘。并且先存储 L0 层的 SSTable 磁盘文件,此时还不需要做文件的合并。每层的所有文件总大小是有限制的(8MB,10MB,100MB… 1TB)。从 L1 层往后,每下一层容量增大十倍。
某一层的数据文件总量超过阈值,就在这一层中选择一个文件和下一层的文件进行合并。
如此这般上层的数据都是较新的数据,查询可以从上层开始查找,依次往下,并且这些数据都是按照时间序列存放的。
监控系统的基本流程
数据采集:采集的方式有很多种,包括日志埋点进行采集(通过 Logstash、Filebeat 等进行上报和解析),JMX 标准接口输出监控指标,被监控对象提供 REST API 进行数据采集(如 Hadoop、ES),系统命令行,统一的 SDK 进行侵入式的埋点和上报等。
数据传输:将采集的数据以 TCP、UDP 或者 HTTP 协议的形式上报给监控系统,有主动 Push 模式,也有被动 Pull 模式。
数据存储:有使用 MySQL、Oracle 等 RDBMS 存储的,也有使用时序数据库 RRDTool、OpentTSDB、InfluxDB 存储的,还有使用 HBase 存储的。
数据展示:数据指标的图形化展示。
监控告警:灵活的告警设置,以及支持邮件、短信、IM 等多种通知通道。
监控体系分层
1、概述:
传统企业的运维经过多年的积累,往往己沉淀下来不少监控工具,有不同专业条的工具,如基础设施、硬件、软件、安全等;也有不同类型的工具,如基于日志、数据库、中间件、操作系统、网络报文等。对于这些工具,我们采用以下方式处理:
1)建立集中监控平台,在一体化运维体系中,监控平台贯穿所有环节,它起到了生产系统涉及的软硬件环境实时运行状况的“监”,监控平台事件驱动的特性也为一体化运维体系起到神经网络驱动的作用,进而进行了“控”,另外,监控平台优质的运维数据可以作为运维大数据分析的数据源,实现运维数据采集的角色。为了提高投入效率,减少重复投入,需要建立集中监控平台实现统一展示、统一管理,支持两地三中心建设,具备灵活的扩展性,支持运维大数据分析;
2)原有的监控工具保留为主:当前并没有哪一个监控工具可以覆盖所有生产系统的运行指标,已沉淀下来的监控工具往往是当前生产系统深度定制的工具,具有存在价值。另外,虽然监控平台从WEB、APP、到DB均采用了多中心双活分布式架构部署,但为保证监控覆盖能力,部分重要的环节仍建议不仅限一套监控工具。
3)各专业条线对各条线的监控负责:各专业条线是最清楚自己需要什么监控的团队,各专业条线对监控覆盖率负责,监控平台的建设方负责平台体系的建设,提供基础技术支撑。
4)工具间整合:不同的专业条线、不同的分析技术可以有不同的监控工具,采用这种多点开花的建设方式更有助于监控面与深度的完善,所有的工具最终需要进行标准化的整合。
基于上面4个处理思路,为防止监控建设失控,减少重复建设、明确主要的建设目标,我们需要对监控工具进行体系化管理,体系化管理首先要做的就是进行监控体系分层。
2、分层方式:
相信每家企业对于监控分层体系都会有各自的划分方式,以下是以专业条线方式分层:
1)基础设施层:包括运营商专线、机房(机房内的设施,比如制冷、安防等)、网络设备,基础设施层的监控分为状态、性能、质量、容量、架构、流量分析等几个层面。
2)系统服务器层:包括系统服务器、存储等服务器的可用性状态。
3)系统及网络服务层:系统及网络服务层主要是指操作系统、系统软件、网络软件的使用情况。
4)应用服务层:应用服务层主要是针对应用服务可用性、应用营业状态、应用性能、应用交易量分析几方面。
5)客户体验层:客户体验层包括两块,一是客户访问速度;二是功能是否正常,具体指的是全部、局部、个别用户或终端访问情况,不仅包括业务系统是否能访问,访问的速度是否快,还包括业务逻辑的验证功能是否正常。
3、各层职责
1)基础设施
状态监控包括机房供电、空调、网络设备的软硬件状态,如设备状态等
性能监控包括设备的性能情况,比如CPU、内存大小、session数量、端口流量包量、内存溢出监控、内存使用率等;
网络监控包括设备错包、丢包率,针对网络设备以及网络链路的探测延时、丢包率监控等;
容量监控包括设备负载使用率、专线带宽使用率、出口流量分布等;
由于基础设施硬件往往已有设备健康性的检测机制,建议向这类厂商提要求,将设备的运行事件主动送到监控平台整合。
2)服务器层
存储:包括存储设备,以及设备上的硬盘读写错误、读写超时、硬盘掉线、硬盘介质错误;
服务器上的内存(内存缺失、内存配置错误、内存不可用、内存校验)、网卡(网卡速率;电源:电源电压、电源模块是否失效)、风扇(风扇转速等)、Raid卡(Raid卡电池状态、电池老化、电池和缓存是否在位、缓存策略)
虚拟机:vcenter等
容器:docker等
存储、物理设备、虚拟机等建议参考基础设施层由厂商主动汇总事件到监控平台,由于容器方面的监控工具并不多,则需根据实际情况选择是否借鉴开源的工具进行自研。
3)系统服务层:
系统服务层的数据主要包括操作系统、中间件、数据库,以及其它开源分布式中间件等工具,这方面包括很多,以操作系统为例,包括:CPU(CPU整体使用率、CPU各核使用率、CPU Load负载)、内存(应用内存、整体内存、Swap等)、磁盘IO(读写速率、IOPS、平均等待延时、平均服务延时等)、网络IO(流量、包量、错包、丢包)、连接(各种状态的TCP连接数等)、进程端口存活、文件句柄数、进程数、内网探测延时、丢包率等。
在分析系统服务层的数据消费情况时,可以通过分析系统性能情况,客观衡量业务负载高低情况,并结合扩缩容调度,实现业务的负载和成本间的平衡。可以根据服务器所在业务层级(接入层、逻辑层还是数据层)的不同,设置不同的容量参考指标、指标参考基准、指标计算规则、高低负载判别规则,设置业务模块(由相同功能的多个服务器构成的业务集群)的扩缩容规则;由系统计算出服务器、业务模块的负载情况,决策出是否需要扩容或缩容,触发业务模块的扩缩容操作。
这一层的工具主要采用引入成熟工具或自研的方式,可选的空间比较大,只要覆盖面够广、支持灵活的二次定制开发,应该问题都不大,建设过程中,我认为中间件与数据库两块是值得让DBA、中间件管理员深度挖掘监控指标覆盖面。
另外,在互联网分布式架构的推动下,传统企业也逐步使用一些分布式中间件,比如分布式数据库中间件,内存数据库、消息队列等。由于对于这类开源中间件,传统企业在技术上弱于互联网企业,且监控工具并不多,需要重点投入资源进行相关监控指标的开发。
4)应用服务层
服务可用性监控:如服务、端口是否存在,是否假死等
应用营业状态监控:指应用的状态是否满足业务开业状态
应用性能:应用处理能力,比如交易量、成功率、失败率、响应率、耗时
应用交易:比如交易主动埋点、交易流水、ESB等
应用服务层监控可扩展的面与深入的度都有很大空间,具体介绍参见公众号另一篇梳理《应用可用性监控建设阶段小结》,以下是一部分应用监控点:
5)客户体验层
比如测速系统以及模拟用户访问的方式:
以模拟用户访问为例,通过模拟用户访问业务并校验返回数据结果,监测业务是否可用、访问质量及性能、逻辑功能正确性的监控系统。不仅仅是接入层(网站类业务是否能访问,访问的速度是否快),业务逻辑的验证就涉及到登录鉴权、关系数据自动化获取等。
监控整合
监控的分层的方式促进了每一个专业层的监控覆盖面与深度,防止建设失控,但也带来一个管理上的副作用,所以需要在事件、可视化、子系统、数据的整合,以减少管理成本。
在监控整合上,主要从事件汇总、统一可视化、监控数据汇总3方面进行梳理。
1、事件汇总
google sre解密一书中提过(大体意思如下):监控应该尽可能简单的把需要人介入或关注的信息展示给运维团队,能通过自动化自愈解决、分析定位过程则不在一级视图提供。当前,能实现自愈的企业还比较少,或还在摸索建设过程中,所以我先讲讲如何让每天产生上亿条流水,触发上万次告警条件(同一告警如未解除会持续不断触发告警条件),来自各种不同工具、不同格式的的告警事件以尽可能简单的方式展示给一线监控团队。
举几个例子:
从可视化角度看,不同的工具有不同的监控事件展示界面,多个运维视图增加了运维技能要求,需要更多的人力去管理生产;
缺少对各类事件进行汇总与数据分析,无法反映生产系统整体的运行状况,如能将这些事件数据汇总起来,比如物理层的拓扑,则可以直观的管控应用状况;
同一个生产问题往往会带来多个维度的生产运行问题,比如一台物理机宕机,在这台物理机上的虚拟机都会出现网络、操作系统层面可用性、应用可用性、交易级状况、应用性能、客户体验的告警,如果监控指标足够丰富往往会有上百条以上,不能准确、快速定位问题根源。
每天能触发阀值的告警很多,以经验的方式很难让一线监控团队无时无刻能准确的定位哪些是高优先级的告警,比如磁盘空间到了70%的确需要有人去关注,评估是否进行数据清理、扩容,但这类告警属于低优先级的事件。
从上面4个例子可以看到,事件汇总模块需要有几个基本要求:
事件汇总:汇总不同层次、不同专业条线、不同类型事件是监控集中管理的基础。
事件收敛:前面提到同一个故障会触发多类指标的告警,同一个指标在故障未解除前也会重复产生大量的告警事件,如果将全部事件都展示出来,那对于监控处理人员将是灾难性的,所以需要进行事件收敛(关于收敛的思路可以见公众号另一篇关于事件收敛的文章)
事件分级:对于不同的事件需要有适当层次的事件分级,事件升级的策略。事件分级是将事件当前紧急程度进行标识显示,事件升级是对于低级的事件当达到一定的程度,比如处理时间过长,则需要进行升级。
事件分析:事件分析是建立事件的关联关系,关联分析可以从纵向和横向关系进行分析,纵向是指从底层的基础设施、网络、服务器硬件、虚拟机/容器、操作系统、中间件、应用域、应用、交易;横向是指从当前的应用节点、上游服务器节点、下游服务器节点的交易关系。事件分析是形成故障树,自愈的基础。对于事件分析重点在于关系模型的建立,互联网公司有不少标准化的方案,但我个人认为需要开发团队介入改造的标准化不可控,所以另外一方向是针对企业内部特点,以CMDB、应用配置库为中心,或以节点型的系统为中心去建立关系模型,具体介绍见第三章。
高性能:为了实现实时监控,需要事件汇总模块具备高性能。
对外提供采集事件数据接口:监控作为一体化运维体系的一部分,需要对外提供服务化接口,支持事件数据的采集。
2、统一可视化
不同监控工具有着不同界面,不同的操作方法,对工具的掌握程度依赖于运维人员的经验,监控管理很难形成标准化,不利于监控的集中管理、释放人力成本。所以,监控事件汇总后,需要有一个统一的可视化,支持统一展示、多类型展示形式、多维用户视角、支持按需订阅的特点。具体包括:
支持事件的统一展示:支持不同角色用户管理不同的事件,包括事件的受理、分派、督办、升级、解除、转工单等闭环操作,无需在不同工具上多次操作。
多类型的展现形式:PC电脑的web端,移动手持端,大屏展示,为了支持可视化的快速开发,以及低成本的过渡到移动手持端,建议采用H5的技术选型。
多维用户:根据不同机构、不同用户的关注点,比如一线运维主要关注实时告警,二线运维主要关注事件丰富与故障树等辅助定位,值班经理主要关注当天监控事件处理情况,团队管理者主要关注团队内监控事件与重要业务系统运行状况,主管经理主要关注整合的运行情况与人员处理情况,开发人员需要有协助处理的视角数据等。
支持用户订阅展示,针对不同的业务运营场景、不同的用户进行布局、推送数据、监控指标的订阅式展示,比如,双十一或秒杀的运营活动,需要关注几十个OS的资源情况,各个OS上的交易、性能情况,如果每一个指标一个窗口,需要看几十个窗口;如果只看告警信息,又无法观察到趋势;所以,需要支持多指标合并在一个视图页面的订阅功能。
3、数据整合标准
关于数据整合,这里不再复述不同监控工具事件数据的整合,主要从报文、日志、数据库流水几个角度分析:
1)报文解释:
市场上有很多APM,大体可以分为主动模拟拨测、页面插入代码监测、客户端插件采集、服务端代理收集、服务端旁路报文监听。以天旦BPC为例,采用服务端的网络层旁路抓取一份报文,通过预先定义好的解码策略,解出了一份数据格式良好的数据源。在这份数据源之上可以进行监控、运维数据分析等运维场景的使用。
2)日志结构标准:
日志结构标准,主要分两类,一类是直接建一个日志分析平台,比如国外的splunk、国内的日志易,或者开源的ELK(很多厂商也是用了ELK);另一类是重构日志标准组件,比如重构java企业应用中经常使用的log4j开源包的标准输出方法,对日志结构进行整合,并通过异步消息的方式将日志发送给监控平台,再提供可视化的IDE对不同系统的日格式进行进一步整理,将需要的数据抽取整合。
3)数据库流水标准:
在监控数据库流水中,也分两类,一类是建立标准的运维流水表,监控直接读取这些流水进行监控或分析;另一类参考重构log4j的思路,对jdbc的包进行重构,将数据库执行语句,以及语句执行过程中的开始时间、结构时间、返回状态进行记录。第一类我们用得比较多,当前的交易级的监控主要采用这种方式进行,第二类目前仍处于思路阶段。
4)其它思路:
其实针对日志LOG4J、数据库JDBC这两种方式从思路看都是从节点类的模块进行,往同类扩展,可以针对标准应用中间件、WEB等模块进行处理;往大的扩展,则比如企业ESB类的应用系统可以作用标准的数据整合。这些节点类的模块进行数据整合标准往往可以有事半功倍的作用。
流行的监控系统
前面讲了监控系统的功能,分类,分层,相信大家对 IT 监控系统都有一定的了解了。
接下来,我们来看看有哪些优秀实践。这里介绍两个比较流行的监控系统:
Zabbix
Prometheus
Zabbix
先来了解下 Zabbix 的架构设计:
Zabbix Server:核心组件,C 语言编写,负责接收 Agent、Proxy 发送的监控数据,也支持 JMX、SNMP 等多种协议直接采集数据。同时,它还负责数据的汇总存储以及告警触发等。
Zabbix Proxy:可选组件,对于被监控机器较多的情况下,可使用 Proxy 进行分布式监控,它能代理 Server 收集部分监控数据,以减轻 Server 的压力。
Zabbix Agentd:部署在被监控主机上,用于采集本机的数据并发送给 Proxy 或者 Server,它的插件机制支持用户自定义数据采集脚本。
Agent 可在 Server 端手动配置,也可以通过自动发现机制被识别。数据收集方式同时支持主动 Push 和被动 Pull 两种模式。
Database:用于存储配置信息以及采集到的数据,支持 MySQL、Oracle 等关系型数据库。同时,最新版本的 Zabbix 已经开始支持时序数据库,不过成熟度还不高。
Web Server:Zabbix 的 GUI 组件,PHP 编写,提供监控数据的展现和告警配置。
产品成熟:由于诞生时间长且使用广泛,拥有丰富的文档资料以及各种开源的数据采集插件,能覆盖绝大部分监控场景。
采集方式丰富:支持 Agent、SNMP、JMX、SSH 等多种采集方式,以及主动和被动的数据传输方式。
较强的扩展性:支持 Proxy 分布式监控,有 Agent 自动发现功能,插件式架构支持用户自定义数据采集脚本。
配置管理方便:能通过 Web 界面进行监控和告警配置,操作方便,上手简单。
性能瓶颈:机器量或者业务量大了后,关系型数据库的写入一定是瓶颈,官方给出的单机上限是 5000 台,个人感觉达不到,尤其现在应用层的指标越来越多。虽然最新版已经开始支持时序数据库,不过成熟度还不高。
应用层监控支持有限:如果想对应用程序做侵入式的埋点和采集(比如监控线程池或者接口性能),Zabbix 没有提供对应的 SDK,通过插件式的脚本也能曲线实现此功能,个人感觉 Zabbix 就不是做这个事的。
数据模型不强大:不支持 Tag,因此没法按多维度进行聚合统计和告警配置,使用起来不灵活。
方便二次开发难度大:Zabbix 采用的是 C 语言,二次开发往往需要熟悉它的数据表结构,基于它提供的 API 更多只能做展示层的定制。
Prometheus(号称下一代监控系统)
先来了解下 Prometheus 的架构设计:

Prometheus Server:核心组件,用于收集、存储监控数据。它同时支持静态配置和通过 Service Discovery 动态发现来管理监控目标,并从监控目标中获取数据。
此外,Prometheus Server 也是一个时序数据库,它将监控数据保存在本地磁盘中,并对外提供自定义的 PromQL 语言实现对数据的查询和分析。
Exporter:用来采集数据,作用类似于 Agent,区别在于 Prometheus 是基于 Pull 方式拉取采集数据的。
因此,Exporter 通过 HTTP 服务的形式将监控数据按照标准格式暴露给 Prometheus Server,社区中已经有大量现成的 Exporter 可以直接使用,用户也可以使用各种语言的 client library 自定义实现。
Push gateway:主要用于瞬时任务的场景,防止 Prometheus Server 来 Pull 数据之前此类 Short-lived jobs 就已经执行完毕了,因此 Job 可以采用 Push 的方式将监控数据主动汇报给 Push gateway 缓存起来进行中转。
Alert Manager:当告警产生时,Prometheus Server 将告警信息推送给 Alert Manager,由它发送告警信息给接收方。
Web UI:Prometheus 内置了一个简单的 Web 控制台,可以查询配置信息和指标等,而实际应用中我们通常会将 Prometheus 作为 Grafana 的数据源,创建仪表盘以及查看指标。
轻量管理:架构简单,不依赖外部存储,单个服务器节点可直接工作,二进制文件启动即可,属于轻量级的 Server,便于迁移和维护。
较强的处理能力:监控数据直接存储在 Prometheus Server 本地的时序数据库中,单个实例可以处理数百万的 Metrics。
灵活的数据模型:同 Open-Falcon,引入了 Tag,属于多维数据模型,聚合统计更方便。
强大的查询语句:PromQL 允许在同一个查询语句中,对多个 Metrics 进行加法、连接和取分位值等操作。
很好地支持云环境:能自动发现容器,同时 K8s 和 Etcd 等项目都提供了对 Prometheus 的原生支持,是目前容器监控最流行的方案。
功能不够完善:Prometheus 从一开始的架构设计就是要做到简单,不提供集群化方案,长期的持久化存储和用户管理,而这些是企业变大后所必须的特性,目前要做到这些只能在 Prometheus 之上进行扩展。
网络规划变复杂:由于 Prometheus 采用的是 Pull 模型拉取数据,意味着所有被监控的 Endpoint 必须是可达的,需要合理规划网络的安全配置。
监控事件
1、监控事件:
监控事件反映的是IT基础设施、中间件、应用程序、业务流程等运行过程中发生的问题。监控系统通过采集运行数据,通过数据判断规则生成事件,监控事件还涉及事件的处理(比如事件丰富、收敛等)、事件的关联分析,并驱动事件的解决。(以下是监控事件处理的一般流程图)

前面提到了事件整合,下面主要讲讲事件关联、事件应急、事件分析、智能处理方面的建设思路。
2、事件标准
1)事件数据模型
事件数据主要包含数据头信息、静态丰富信息、事件现场信息、知识库信息、关联信息。
2)事件分级标准
前面提到了事件分级的问题,分级是将事件当前紧急程度进行标识显示,事件升级是对于低级的事件当达到一定的程度,比如处理时间过长,则需要进行升级。我们将监控事件等级事件级别分为通知、预警、故障三种:
• 通知:指一般的通知信息类事件。
• 预警:指已经出现异常,即将要引起生产故障的事件。
• 故障:指已经发生问题,并且已经影响到生产流程的事件,如果需要进一步细化故障级别,可以分为一般故障和紧急故障:一般故障不需要紧急处理的故障,紧急故障需要管理员紧急处理的故障。
事件细分的粒度需根据各企业团队的管理要求而定。
2、事件关联:
1)事件压缩及收敛
事件压缩及收敛就是为了减少事件数量,提高事件定位能力。监控采集数据后,根据具体的单指标或多指标的规则判断是否触发事件,如触发事件,则发送事件接收器。为什么不直接通过可视化方式马上将匹配到的事件信息呈现给监控人员呢?
那是由于监控数据采集是实时采集,但事件的解决可能并非马上解决,为了减少重复性的告警数量,需要由事件处理引擎进一步压缩处理。比如每2分钟采集一次文件系统容器数据,当某个文件系统容量超过70%后,触发了预警阀值,但这个文件系统是缓慢增长,计划在当周的扩容窗口集中变更,如果不对事件进行处理,那每2分钟就会有一个预警,产生预警泛滥,所以这时需要对事件进行压缩,比如针对事件来源、关键字组合等规则进行压缩,并记录事件发生次数。
有了事件压缩还不够,因为触发事件的指标往往是相互关联的,这就需要对多项指标关系进行分析,减少相同问题产生的事件。比如这个应用场景:
-NAS监控:NAS文件系统在各OS上都会有监控,一个NAS文件系统出问题时,每个服务器的NAS文件系统监控都会报警。如能对NAS进行挂载关系梳理,同一NAS的报警可以大量收敛。
-进程、端口、通讯检测:一个进程宕掉时,该进程启动的端口、关联系统与改进程端口的通讯等都会同时报警。如能对进程、端口、通讯关系进行梳理,同一个进程引发的进程、端口、通讯监控事件也能收敛明显。
2)事件丰富
事件丰富包括事件描述丰富(通过CMDB丰富、拓扑丰富)、事件现场丰富(指标信息丰富、APM信息丰富、系统资源信息丰富)、知识库丰富,提高运维人员分析问题的能力。事件主要丰富方法如下:
-与第三方监控系统对接,获取事件相关信息进行丰富。如与CMDB系统对接,获取服务器等相关配置信息进行CMDB数据丰富;
-根据拓扑关系模型,进行拓扑丰富;
-指标信息丰富:获取事件发生前后一段时间内的相关指标信息数据(如CPU/内存等),进行指标信息丰富;
-相关事件丰富:根据拓扑关系模型、应用关系关联模型、交易流行关联模型将相近事件时间范围内的事件进行丰富展示;
-知识库丰富:建立事件处理方案知识库,记录事件处理的方法和流程,为事件处理人提供参考依据,以及为后续自动化运维提供理论支撑。
3)事件扩散
事件发生之后,监控系统需要能自动分析事件的关联信息,帮助运维人员尽可能的还原事件现场,提高分析问题的能力,关联信息主要有纵向和横向的关系,其中纵向的关联是把基础设施、网络、系统、应用域、应用、交易关联起来,任何一个环节出问题,向上计算出波及范围和受影响系统;横向的关联是以交易为中心,计算上下游的交易节点。下面分别是两个关联:
纵向关系:
横向关系:
4)事件触发
系统在设置报警策略时,可针对指标进行触发条件设置,触发条件按照类型分为阈值触发、基线触发、智能预测。系统根据不同的触发类型设置,采用的判断方式也不一样。具体明细如下:
• 阈值触发
系统支持指标的阈值触发设置,当指标值达到设置的阈值时即可进行报警。
- 阈值的设置范围只能在该指标的数值范围内进行设置。
阈值在设置时需要指定数值单位,防止数值因单位不同出现判断错误。
在设置阈值时系统支持实时查看指标当日折现图和历史基线,帮助运维人员正确判断阈值的设置范围。
• 基线触发
系统支持指标的基线触发设置,当指标值达到设置的基线时即可进行报警。
-基线设置可按照昨日基线、月基线、周基线进行设置。
-系统支持在选定的基线基础上进行上浮或下沉幅度的设置。
-在设置基线时系统支持实时查看指标当日折现图和历史基线,帮助运维人员正确判断基线的设置范围。
-系统支持按照平均基线进行设置。
-基线设置时需要有一定的历史数据作为依据。
• 智能预测
智能预测主要是通过历史数据的分析,通过人工智能算法预测未来可能出现的问题,这一块是未来监控事件优化的一个方向。
3、事件应急
1)应急恢复
运维最基本的指标就是系统可用性,应急恢复的时效性是系统可用性的关键指标。通常来讲应急恢复的方法有不少,比如:
• 服务整体性能下降或异常,可以考虑重启服务;
• 应用做过变更,可以考虑是否需要回切变更;
• 资源不足,可以考虑应急扩容;
• 应用性能问题,可以考虑调整应用参数、日志参数;
• 数据库繁忙,可以考虑通过数据库快照分析,优化SQL;
• 应用功能设计有误,可以考虑紧急关闭功能菜单;
• 还有很多……
监控系统的事件丰富过程中需要尽可能关联上述的一些应急手段,供运维人员快速应急,比如服务启停工具、切换工具、程序回切工作等,比如下面这个应用服务启停工具例子:

2)现场保护
故障处理中,理论上应该在应急前进行现场保护以备问题原因排查的跟进。现场信息主要包含进程内部状态信息、日志信息。实际应用过程中可以结合工具进行现场保护,仍以服务启停工具为例,支持获取进程线程镜像信息、进程内存镜像信息及GC日志信息。

3)问题排查
• 是否为偶发性、是否可重现
故障现象是否可以重现,对于快速解决问题很重要,能重现说明总会有办法或工具帮助我们定位到问题原因,而且能重现的故障往往可能是服务异常、变更等工作导致的问题。
但,如果故障是偶发性的,是有极小概率出现的,则比较难排查,这依赖于系统是否有足够的故障期间的现场信息来决定是否可以定位到总是原因。
• 是否进行过相关变更
大部分故障是由于变更导致,确定故障现象后,如果有应的变更,有助于从变更角度出现分析是否是变更引起,进而快速定位故障并准备好回切等应急方案。
• 是否可缩小范围
一方面应用系统提倡解耦,一支交易会流经不同的应用系统及模块;另一方面,故障可能由于应用、系统软件、硬件、网络等环节的问题。在排查故障原因时应该避免全面性的排查,建议先把问题范围缩小到一定程序后再开始协调关联团队排查。
• 关联方配合分析问题
与第(3)点避免同时各关联团队同时无头绪的排查的同时,对于牵头方在缩小范围后需要开放的态度去请求关联方配合定位,而对于关联方则需要有积极配合的工作态度。
• 是否有足够的日志
定位故障原因,最常用的方法就是分析应用日志,对运维人员不仅需要知道业务功能对应哪个服务进程,还要知道这个服务进程对应的哪些应用日志,并具备一些简单的应用日志异常错误的判断能力。
• 是否有core或dump等文件
故障期间的系统现场很重要,这个在故障应急前建议在有条件的情况下留下系统现场的文件,比如COREDUMP,或TRACE采集信息等,备份好一些可能被覆盖的日志等。
4)应急文档
故障的表现虽然形式很多,但实际的故障处理过程中,应急措施往往重复使用几个常用的步骤,所以应急文档首先要针对这些常用的场景,过于追求影响应用系统方方面面的内容,会导致这个方案可读性变差,最终变更一个应付检查的文档。以下是我觉得应用系统应急方案应该有的内容:
(1)系统级:
能知道当前应用系统在整个交易中的角色,当前系统出现问题或上下游出现问题时,可以知道如何配合上下游分析问题,比如:上下游系统如何通讯,通讯是否有唯一的关键字等。另外,系统级里还涉及一些基本应急操作,比如扩容、系统及网络参数调整等。
(2)服务级:
能知道这个服务影响什么业务,服务涉及的日志、程序、配置文件在哪里,如何检查服务是否正常,如何重启服务,如何调整应用级参数等。
(3)交易级:
能知道如何查到某支或某类交易出现了问题,是大面积、局部,还是偶发性问题,能用数据说明交易影响的情况,能定位到交易报错的信息。这里最常用的方法就是数据库查询或工具的使用。知道最重要的交易如何检查是否正常,重要的定时任务的应急处理方案,比如开业、换日、对账的时间要求及应急措施。
(4)沟通方案:
沟通方案涉及通讯录,包括上下游系统、第三方单位、业务部门等渠道。
另外,有了应急方案,如何让运维人员持续去更新是难点。我认为要解决这个难点,需要先让运维人员经常使用这个手册。如果一个手册没有场景可以用,那就需要管理者为运维人员创造机会去使用这个手册,比如应急演练。
持续优化
1、整体思路
监控系统建设目标是完善“监”能力,增加“控”的能力,这章提到的持续优化主要是针对“监”能力的落实,归纳起来就是“不漏报,少误报”,可以针对不同的阶段量化目标,比如60%告警即故障,80%故障来自监控。
2、措施
1)目标分解:
• 不漏报
漏报可以从两个层面看,一个是监控工具不具备某一方面的监控能力;一个是监控工具具备监控能力,但因为使用者使用问题导致未覆盖监控。前者需要完善监控能力,比如针对生产故障举一反三式的优化,或由不同专业条线主动增加监控能力;后者则需要考虑几个问题:
-管理上有没有要求指标的100%覆盖率
-覆盖率的要求是否确实可以落地,或功能上是否设计极不友好
-100%的覆盖率是否从技术默认设置,如果技术无法默认设置,能否从技术上主动发现
前面两个问题需要从管理手段上解决,最后一个问题需要在监控系统中解决,即尽可能让需要覆盖的监控指标从技术上落地,减少对运维人员主动性上的依靠,同时监控系统要快速从技术上响应新的监控指标的落地。
• 减少误报
误报带来的问题也很大,大量、反复的误报告警会让运维人员麻木,进而忽视监控报警,错过了真正的监控事件的处理,所以监控误报情况也需要重视。
文章来源:twt企业IT社区、51CTO技术栈
如有侵权请联系我们

—END—
第三波软件(北京)有限公司为宏碁(股)100%转投资之子公司,针对宏碁公司提出以「BYOC(自建云)」做为变革转型的新愿景,从硬件公司转型成为【硬件+软件+服务】的企业,并以王道思维与合作伙伴共创价值、建立利益平衡的产业生态。


