【Prometheus】监控系统概述
现在开始一个新的系列,【Prometheus】,主要参考《深入浅出Prometheus》,基本为其读书笔记加上部分自己的理解
概览
在本系列中,监控系统特指对数据中心的监控,包括硬件和软件的监控和告警
监控系统的作用:
- 实时监控。提供硬件和软件的运行状态展示
- 告警。符合预设告警阈值则通过多种方式发送告警信息
- 辅助决策。大数据监控不仅提供实时状态展现,更能帮助故障回溯和预测风险
根据程序设计的角度来分类,监控的种类如下,每种监控都涉及不同的监控指标,不同的收集方式,具体在下文分析
基础资源监控
网络
- 网络性能监控。涉及网络监测、网络实时流量监控(网络延迟、访问量、成功率等)和历史数据统计、汇总和历史数据分析
- 网络攻击检查。针对内网或者外网的网络攻击如 DDoS 攻击等,通过分析异常流量来确定网络攻击行为
- 设备监控。对数据中心的网络设备监控,如路由器、防火墙、交换机,通过SNMP协议收集
服务器
监控分类:
- 主机监控。服务器硬件来源于不同厂商,需要获取不同厂商的服务器硬件信息
- 虚拟机监控。不同的操作系统如 Windows、Linux,采集软件需要做到跨平台运行以获取对应的指标
- 容器监控。兼容各种虚拟化环境如虚拟机(KVM、VMware、Xen)及容器(Docker、rkt)
采集方式有两种:
- 主机监控。IPMI(Intelligent Platform Management Interface,智能平台管理接口)实现。IPMI是一种标准开放的硬件管理接口,不依赖于操作系统,可以提供服务器的风扇、温度、电压等信息
- 虚拟机监控。一是内置客户端。在每台机器上安装采集客户端。二是在虚拟机环境下通过Xen API、VMware Vcenter API获取监控数据
- 容器监控。Docker API或针对不同服务/中间件开发的采集器exporter作为一个运行容器进行导出
采集指标:
- CPU。CPU使用量、用户态百分比、内核态百分比、每个CPU的使用量、等待队列长度、I/O等待百分比、CPU消耗最多的进程、上下文切换次数、缓存命中率
- 内存。使用量、剩余量、内存占用最高的进程、交换分区大小、缺页异常数
- 网络I/O。涉及每个网卡的上行流量、下行流量、网络延迟、丢包率
- 磁盘I/O。涉及硬盘的读写速率、IOPS、磁盘用量、读写延迟
中间件监控
中间件监控需要针对不同中间件的特点和属性分别监控,目前并没有统一的标准和规范
例如,针对 Kafka 的性能监控通常需要采集 Kafka 集群的 Topic 个数、Broker 数据分区数量、日志 Offset值和生产消费流量等指标
针对 Redis的性能监控通常需要采集 Redis 的内存使用量、连接数和缓存命中率等指标
解决方案通常是分别开发一个数据收集 Agent,该 Agent 将采集中间件的性能指标并将其统一转化成 JSON、文本或者其他监控系统能识别的数据格式,然后汇总到监控中心
Prometheus针对不同的中间件开发了对应的监控代理,例如Kafka exporter、MySQL server exporter、Apache exporter、Redis exporter等exporter,它们负责采集这些中间件的特定指标,并提供HTTP查询接口
应用程序监控(APM)
采集的方法是将采集器运行在容器内,导出所有容器运行的数据
- 调用链跟踪。从用户发送请求到后端API服务,以及API服务和关联的中间件或者其他组件之间的调用,构建出一个完整的调用拓扑结构
- 性能监控。监控组件内部方法的调用层次(Controller→Service→DAO),获取每个函数的执行耗时,从而为性能调优提供数据支撑。还能截获TCP、HTTP网络请求,从而获得执行耗时最长的方法和SQL语句、延迟最大的API等信息
- 运行状态监控。根据业务指标、日志指标、调用链指标、应用环境指标、应用集群指标、服务组件指标、线程栈和客户端体验数据等,形成全维度的指标,展示为服务运行状态
日志监控
日志监控采集日志数据(文本类型),并将这些数据汇总到日志存储和搜索引擎中,提供日志检索的 Web 接入。指标监控的对象通常都是数字,而日志监控的对象是文本数据,这就要求存储系统具备文本检索功能
下面是流行的日志监控黄金组合:
- Fluentd:日志采集,还有Filebeat、Flume、Fluent Bit,也有一些应用集成Log4g等日志组件直接输出日志
- Kafka:数据整流合并,避免突发日志流量直接冲击Logstash
- Logstash:日志整理,完成日志过滤、日志修改等功能
- Elasticsearch:日志存储和日志检索,自带分布式存储,可以将采集的日志进行分片存储
- Kibana:日志查询组件,负责日志展现,主要通过Elasticsearch的HTTP接口展现日志
监控系统实现
总体架构
- 指标采集子系统。负责信息采集、过滤、汇总和存储
- 数据处理子系统。负责数据分析、展现、预警、告警动作触发和告警
指标采集子系统
数据采集
- 通过客户端进行数据采集。针对特定的设备和系统开发的采集器。客户端会将采集到的数据上报到监控中心节点进行汇聚存储。这种方式比较灵活,在理论上任何对象都是可以被监控的。但客户端本身需要一定的开发工作,采用侵入的方式安装客户端也存在安全和性能风险
- 通过标准协议进行数据采集。优点是数据规范统一、普适性更广,所有Java应用都可以实现 JMX 协议,从而完成应用指标监控。但目前数据中心内的软硬件各异,设备和软件对协议的支持也不完善,在很大程度上限制了通过协议进行数据采集的能力
数据传输和过滤
- HTTP、Socket连接进行点对点传输。如果 Agent(采集器)是一个 HTTP 服务端,那么采集中心节点会周期性调用 Agent 的接口获取数据,这种方式被称为 Pull(拉取);相反,如果 Agent是一个 HTTP客户端,它就会调用中心节点的 HTTP服务,将数据发送到中心节点,这种方式被称为Push(推送)
- RabbitMQ、Kafka等消息中间件进行传输。使用消息中间件传输的方式在结构上充分解耦。消息中间件不仅可以将监控数据进行一定程度的持久化,而且可以对监控数据进行整流,避免突发流量冲击数据收集组件。但会造成整个系统对中间件的强依赖,如果中间件发生故障,则可能导致整个系统发生故障,并且消息中间件在安装部署及后期的运维中都比较复杂。
HTTP 传输的方式虽然有一定的耦合度,但系统可以足够简单,易于扩展和维护,大部分开源监控系统都采用这种方式
在持久化之前,通常还需要对收集的数据进行简单去重和过滤,主要有以下几个场景:
- 客户端重复上报数据。网络不稳定等因素
- 去除无用指标。客户端上报的指标通常是全集,而有些指标是系统并不关注的
数据存储
对监控数据的存储通常借助于时序数据库。监控数据的最大特点是有时间属性,每个监控数据都有一个时间维度(属性),被称为时序数据,展现了一个物体的某些特征在一段时间内的变化情况
时序数据的特点:
- 一次性写入多次读取。时序数据通常不会修改更新,一旦存入,则后期只会对数据进行查询操作
- 数据流持续平稳且量大。时序数据量往往和采集点的数据量成正比,不会出现业务系统流量突增的情况,并且数据流是持续稳定的,通常间隔一个稳定的采集周期来获取数据。但存储的数据量会慢慢变得非常大。
- 查询方式以时间为维度,数据查询通常会指定一段时间,并且热数据通常都是最新采集的数据。在实际场景中通常查询最近几个小时的监控数据
所以,与关系型数据库采用B+树不同,时序数据库通常采用LSM树,提供更好的写性能。因为LSM树存储框架实现的思路较简单,其先在内存中保存数据,再定时刷到磁盘,实现顺序IO操作,通过定期合并文件减少数据冗余;文件有序,保证读取操作相对快速。适用于写多、读相对少(或较多读取最新写入的数据,该部分数据存在内存中,不需要磁盘IO操作)的业务场景
数据处理子系统
数据查询
通过展现层(浏览器或者客户端)多维度展现实时数据和历史数据。实时数据查询严格要求数据的准确性和实时性,查询接口需要迅速响应
另外,可以通过一些Web工具,把后端分析的数据以可视化的方式展现。比如:
- 折线图能够很好地展现数据变化的趋势
- 饼状图能更好地展现系统中各个子模块的占比
- 柱状图的优势在于对数据的对比
数据分析
- 性能分析:分析某个应用在特定时间段内的资源消耗情况,可以将应用按照资源消耗的特点分类。当应用程序出现性能问题时,要能够通过性能分析确定故障点,并在故障发生后回溯故障发生的原因
- 关联分析:每个监控数据都存在多个维度,通过关联分析可以找出数据之间的关联。在 APM 监控中,通过相同 TraceId 的关联,可以构建出程序的调用链信息,这样不仅可以分析出组件之间的调用关系,还可以分析出每个调用的耗时,从而优化系统性能
- 趋势分析:对采集数据指标进行分析,再结合平均数算法、指数平滑算法、Holt线性趋势算法或其他机器学习模型如自回归积分滑动平均,分析时序数据内在的周期性,得出未来的变化趋势。可以用于实时资源调度、预分配资源,还可以辅助数据中心的硬件采购
基于规则告警
利用已经采集的监控数据,匹配用户自定义的多维度告警规则,如果满足,则触发相应规则的告警。例如,性能告警规则一般是设定某个阈值、触发次数和告警行为
还有一些告警属于异常告警,例如服务器宕机、网络不通等情况,通常不需要设定告警规则。如果某个告警规则被触发,则在接下来的一段时间内,为避免相同的告警被多次触发,需要进行告警抑制
对告警的处理,会按照用户预先设定的告警动作执行对应的操作,通常会发送短信、邮件或者触发用户定义的 webhook。高级的告警处理可以执行告警的恢复脚本,先在系统中预先设定一些常用的恢复脚本,系统能够根据发生的不同事件,判断并使用不同的脚本处理告警事故