本文根据老师在〖deeplus直播:去哪儿网可观测性实践〗线上分享演讲内容整理而成。(文末有回放的方式,不要错过)****
肖双
去哪儿网 基础架构部技术TL
2018年加入去哪儿网,目前负责去哪儿网 CI/CD、监控平台和云原生相关平台建设。
期间负责落地了去哪儿网容器化平台建设,协助业务线大规模应用迁移至容器平台,完成监控系统 Watcher 2.0 的改造升级和根因分析系统落地。对监控告警、CI/CD、DevOps 有深入的理解和实践经验。
分享概要
一、以始为终,用故障指标来衡量监控系统的完善度
二、订单类故障秒级发现
三、复杂故障,如何分钟级定位原因
四、总结
一、以始为终,用故障指标来衡量监控系统的完善度
早期介绍内部监控系统时,我们会分享存储量、报警量等一些核心监控指标量。随着监控迭代,我们逐渐产生疑问:这些监控系统指标究竟对业务有多大帮助?
1.故障数据分析
去年,我们对公司的故障数据进行分析,发现:
故障平均发现时间在4分钟左右
订单类故障1分钟的发现率20%
处理时长超过30分钟的故障比例48%
这些指标仍有很大提升空间,基于以上数据,我们参考MTTR对指标进行优化。
MTTR将故障划分为发现阶段、诊断阶段和修复阶段三个阶段,所以我们可以针对每个阶段制定对应工具,来缩短整体的MTTR。
二、订单类故障秒级发现
我们在去年明确了目标——订单类故障一定要做到秒级发现。
1.现状
实现秒级故障发现之前,根据现有监控系统,梳理了秒级监控系统的建设要点:
**采集使用Graphite协议:**指标的采集和格式都是遵循Graphite协议,而建设秒级指标时必须考虑其兼容性。
**存储IO高,占空间大:**之前TSDB采用的Graphite的Carbon+ Whisper,Whipser因为空间预分配策略和写放大问题,会导致磁盘IO高以及磁盘空间占用过多。
**分钟级设计:**数据采集、上报、报警等模块都是分钟级设计,采集使用Pull模式,定时每分钟拉取。
2.存储方案选型
当时对比了两个TSDB,也就是M3DB和VM(VictoriaMetrics)。
1)M3DB
优点:
高压缩比,高性能
可伸缩
支持Graphite协议以及部分聚合函数:业务场景中,聚合函数使用频繁、使用场景复杂
缺点:
部署维护复杂
社区活跃度低
更新迭代慢
2)VictoriaMetrics
优点:
高性能,单机读写可达千万级指标
每个组件都可以任意伸缩
原生支持Graphite协议
部署简单
社区活跃度高,更新迭代快
缺点:
针对Graphite聚合读场景下,性能下降严重
3.压测数据
针对VM进行压测:
压测后发现,磁盘的使用量较低(40G),整体的性能消耗较低。但使用大量聚合指标或大量聚合函数查询时,性能下降非常严重,甚至超时。
4.存算分离
基于以上特点,我们对VM做了存算分离。
因为VM的优势是单指标查询场景性能非常好,所以我们利用VM做单指标查询,使用上面的聚合层(CarbonAPI)计算所有的聚合函数。
聚合层(CarbonAPI)的优势在于,它是无状态的,可以任意扩展,在此基础上可添加任何策略、数据监测功能、聚合逻辑、限流和垄断等能力。
在这套架构下,需要多引入一个元数据DB,用以存储所有指标信息(哪些指标在VM集群中的位置)。
用户查询时,先查询CarbonAPI,CarbonAPI从元数据DB拿到指标存储的信息,再去VM里拿出对应的数据,在聚合层做聚合计算,最后将数据传回去。
在聚合层(CarbonAPI),我们还制作了一些定制化的功能。
5.指标采集
存算分离解决了VM的短板问题,第二个任务是实现指标采集、报警的秒级处理。
1)Client端现状
原先使用的是自研客户端,下图右方是客户端架构。
在早期实现时,使用Counter.Incr()计算指标自增,它会将数据放到到本地的指标仓库里,这个指标仓库实际在应用程序的客户端也就是内存中。
同时,异步调度器每隔一段时间(可能是分钟级)生成数据快照,因而Server端拉取快照时,每分钟拉取的快照是固定的。如果一分钟内多次拉取,也是固定快照。
这样处理的好处是Server端异常时,补偿拉取的数据也不会变更,数据准确度较高。缺点是调度器固定地每分钟调度生成数据快照,指标仓库只支持分钟级数据的存储。
2)Client端改造
**指标仓库方案1:**参考Prometheus的模式Client不做快照只做数据累加或记录,由Server端在拉取时做默认的增量计算
优点:客户端节省内存,无需存储多份数据
缺点:Server端做增量计算,压力较大;采集架构改动过大,且可能存在数据精度问题
**指标仓库方案2:**客户端多份数据计算和存储,生成多快照
优点:采集架构改动小,没有数据精度问题, server 压力小
缺点:会多占用一部分内存
优化:使用Tdigest做数据采样,内存占用量可接受
3)Server端现状
早期Server端进行指标采集时,使用Python+多进程的模型开发,master节点每分钟发全量任务给work节点,这是典型的producer worker架构,其优点是worker节点可以随意扩展。
问题:
任务量大时通过MQ派发耗时长:比如每隔十秒派发十几万的采集任务,采集任务通过MQ派发到worker再进行消费时,过程时间可能已经超过十秒,这种场景下无法做到高频采集。。Python做大量聚合计算时,CPU消耗高
4)Server端改造
其实还是master和worker的架构,但拆去了MQ。现在worker变成有状态的节点,一旦worker启动,任务被master调度给worker,master通过ETCD检测到worker挂掉后,就会启用rebalance,节省了任务配发的过程。
6.最终架构
秒级监控的最终架构核心分为三个部分:数据采集、数据查询以及报警。
实践效果层面,帮助业务线将订单故障发现实践由三分钟提升到一分钟。
三、复杂故障,如何分钟级定位原因
微服务化后定位难的问题聚焦在:
**链路复杂:**相较于单体等架构更复杂
依赖复杂:应用依赖的资源多种多样,依赖的外部资源也越来越多
1.链路与指标关联-精准定位
链路部分在内部称为Qtracer,监控系统叫Qmonitor。
为什么要关联这两部分呢?
我们发现,报警(一般是指标报警)之后,如果应用的QPS很高,会查找到很多trace。由于不确定哪条链路与指标有关系,所以反而干扰快速定位。
比如有三个入口,进来的流量形成了三条trace,它们的代码路径可能都不经过这个指标,所以不会报警。或者是只有一条trace经过这一报警指标,用剩下两条trace做故障定位就没有意义。
所以我们将指标放到了Qtracer里,Qmointor在调用指标计数时,会检查当前是否有trace环境。如果有trace或者span,就将当前这个指标放进span。
如果指标发生告警,就能直接根据这个指标关联到真正经过这个指标的流量,再用这些trace定位,效率显著提高。
告警面板
右侧搜索出trace后,我们会初步对这个trace上的应用进行异常检测,比如哪些应用有异常日志、异常告警,应用依赖的资源是否都正常,容器运行环境是否正常等状况,并将这些 异常展示在面板,辅助开发定位问题。
2.自身依赖快速排查-应用概览
将每个应用最核心的指标、状态以及关注的内容聚合,形成应用概览。如果应用出现问题,可以在应用概览中快速浏览,快速感知应用是否健康。
**应用概览提供两点信息:**入口的请求列表和出口的请求列表。
入口请求列表指提供了哪些服务,即别人请求的服务。请求哪些接口、接口平均QPS、异常率、平均响应时长等相关信息,以及趋势图都可以在面板中查看。
出口请求列表指你的请用请求了别人接口或下游服务,你可以在应用概览中了解目标应用、其平均QPS、请求外部的异常率、响应时长等信息。
实际应用中,开发看到以上信息就能够判断应用状态是否正常。
3.自身依赖快速排查-依赖详情
4.自动分析平台
自动分析平台的运行逻辑是先采集Qtrace,根据trace查看链路异常,然后自动分析平台推荐权重比较高的异常。
以上是自动分析平台简单的模型图。
最底层是知识图谱的挖掘,知识图谱对自动分析非常重要,应用依赖、运行容器、机房信息等内容都需要知识图谱记录,形成行为的分析基础。
行为分析出异常信息,再经过权重体系的评估打分与排序,最终将可能的异常推荐出去。
1)知识图谱
**基础数据:**统一的事件中心、日志、trace、监控告警、应用画像(应用基础的元配置)等。
**应用关联关系建立:**服务调用链、强弱依赖关系
**资源关联关系建立:**应用依赖的各个资源关系、物理拓扑感知 - 感知运行在容器扩kvm的应用的宿主机以及网络环境
**异常之间关联关系建立:**通过异常指标能精确快速的找到对应的trace、log等,异常的告警之间的关联关系挖掘
2)应用分析
3)链路分析
QPS高时,即使已经精确关联,但一分钟内找到的trace依然很多,所以需要筛选或收敛至
较小范围。
筛选分类:
异常trace筛选:重点关注,首先分类
T值分类筛选:基于业务入口垂直分类
拓扑相似度筛选:比较A入口与B入口trace相似度并筛选
如何定位可能是根因的APPCode?
以报警APPCode为顶点找到联通子图。
遍历子图:
在Trace链路上标记为异常的AppCode
计算报警浓度,报警浓度高于一定阈值的AppCode
当前有L1/L2级别告警的AppCode
分析trace链路链路中各应用调用的接口关系,并查看接口监控的错误率和延时是否正常,不正常的标记为异常AppCode
针对AppCode,进行更细维度的异常探测。
4)剪枝排序-权重体系
权重分为四种:
静态权重:经验权重,每年或每段时间会根据故障原因进行调整。
动态权重:root case权重,根据各个根因的严重级别对自己进行升级,避免真正的根因被淹没。
应用权重:代表当前故障中此应用异常所占的权重比,表示此应用影响故障应用的概率大小。
强化依赖权重:强弱依赖可以明确表明,A应用的 m1接口依赖B应用的 m2接口是强依赖还是弱依赖,根据此信息可以确认影响概率。
应用权重计算方式:
收敛Trace,在Trace收敛过程中,计算异常AppCode,对异常AppCode的权重进行累加应用距离,距离告警AppCode越近的App权重越高
如上图所示,三个trace都是A入口,第一次发现C异常,C的权重会加一;第二次发现C异常,权重继续累加,由此计算出应用权重。
除此之外,应用权重还受到应用距离的影响。在酒店的业务场景下,我们认为A和B的距离越近,A导致B异常的可能性就越高,A的权重位越高。
强弱依赖剪枝:
当A 出现告警,B 和C都有 root case异常且B是弱依赖C是强依赖,则倾向认为A的告警由C的异常造成。
5.结果输出
结果会提示有什么发布,root case占比,哪些异常需要重点关注。
6.实践效果
上图是我们实际的线上故障场景,比如出现MYSQL线程异常、负载特别高的情况,就会在结果输出的界面提示出来。
经过以上改动,现在定位慢的故障比例降低20%,根因定位的准确率在70%-80%。
四、总结
用故障的MTTR指标来运营、优化、建设我们的监控体系
秒级监控主要解决高级别故障发现时长的问题
协助故障定位,要在链路复杂和依赖复杂的情况下确认应用的依赖组件以及依赖应用的健康状况,并计算相关异常与此次故障的权重
Q&A
Q1:放在span里的指标具体是指什么?数据模型是怎样的?
A:举个例子,比如有个接口叫false,需要做QPS的监控,指标就命名为false-QPS。一般请求进入的时候,该指标就会被计数。同时,我们会查看是否有trace、span,如果有,就将指标名放入span,进一步关联trace id。通过后期洗数,我们能在ES里做索引,就能够通过指标搜索到trace了。
这个数学模型比较简单,trace id里可能有很多span,span可以理解为一个大JSON,将metric放入span,就能实现关联。
Q2:智能分析使用了哪些技术栈或工具栈?
A:语言层用的是Go,算法包括调度算法、离群检测、权重等方面。
Q3:怎么把控指标仓库中的数据精度?有什么样的评判标准?
A:数据精度由客户端或者SDK控制。比如0秒开始生成快照,生成了0-59秒的快照数据。无论Server端怎么拉取,新的数据存放在新的仓库里,所以数据互不干扰。
数据精度在不同的业务场景下有不同要求。大部分业务场景下,监控数据丢一两个,问题不会太大。如果是订单类场景,丢数据的问题就比较大。
Q4:权重体系中不同权重占比大概是多少?
A:目前没有使用权重占比,整体类似于评分系统,不同的权重累加评分,最终筛选出评分高的指标。我们可以把权重的区间设置好,它基于自身区间或情况可以自行升级。
Q5:服务的强弱依赖怎么确定,是事前通过静态配置吗?还是在动态运行时根据某个规则判断?
A:强弱依赖由另外系统提供数据。去哪儿网实行混沌工程,其中一项内容就是强弱依赖治理。我们在业务线进行常态化的强弱依赖治理,并留存这些数据。
Q6:目前告警治理和运维团队使用哪些线上化工具系统?如何考核应用业务团队,量化SLA指标绩效考核,还是事故统计?
A:量化SLA指标,业界有个最常用的办法就是使用燃尽图统计故障。比如团队定的SRO是四个九,意味着一年只有50多分钟的故障时长。
**获取本期P**********PT,********请添加群秘微信号:dbayuqing
↓点这里可回看本期直播********