一 写在前面
互联网工程的高速发展,分布式、微服务、容器化架构的流行,互联网已全面进入云原生时代。构建系统的方式由最初的单体大应用演变为分布式架构,一台服务器可能仅存几小时甚至几分钟,这种复杂性大大增加了把系统运行状态可视化的难度。
高德打车业务的发展历程也不例外,同样经历了从单体大应用到服务化拆分的过程,庞大的应用体系和架构的不断升级,保障了多个节假日出行高峰的稳定,业务仍在持续快速的发展中,如何保障这套庞大又复杂的系统持续高性能、高可用、高可控?构建360度无死角的多维度可观测能力显得愈发重要。
二 谈系统可观测性
1 什么是系统可观测性
可观测性(observerbality),是一个最近几年开始在监控社区流行起来的术语,可观测性的提出最早来自于 Google 著名的 SRE 体系和 Apple 工程师 Cindy Sridharan 的博文《Monitoring and Oberservability》,感兴趣的同学可以看一下。
可观测性不是一种具体的工具或技术,更偏向于是一种理念,目前已成为复杂分布式系统成功管理的关键组成部分,它是指运行中的系统可被调试的能力,这种可调试能力的核心就是能够在系统运行时对其理解、询问、探查和调度。
理解,询问,探查体现在帮助工程师发现问题 -> 定位问题 -> 解决问题(止损),调度体现在可根据系统运行状态做出的自动化,智能化决策的能力。
可观测性的目标是增强工程师对系统运行状况的了解,增强对系统的信心。
目前,业界广泛推行的可观测性包含三大支柱:日志事件(Logging),分布式链路追踪(Tracing) 和 指标监控(Metrics)。
Logging:不能单纯的理解就是日志,泛指的是应用运行而产生的可以详细解释系统运行状态的各种事件,日志记录是其中最常用一种手段。
Tracing:全链路追踪,面向的是请求,通过对请求打标、透传、串联,最终可以还原出一次完整的请求,可帮助工程师分析出请求中的各种异常点。
Metrics:是对Logging事件的聚合,泛指各种指标监控和大盘,通过多维度聚合、分析和可视化展示,帮助工程师快速理解系统的运行状态。
2 可观测性与监控的关系
可观测性 != 监控
第一印象很容易把“可观测性”认为就是“监控”,人类一般倾向于用之前的认知来理解一些新概念,其实两者是不一样的。
监控是机器代替人工,长期的观察系统的行为和输出,帮助团队观察和了解其系统状态的工具或技术解决方案。监控与可观测性的区别如下:
关注点不同
监控更多关注的是具体指标的变化和报警,关注系统的失败因素,多与运维相关,强调从外到内,从外部通过各种技术手段去看到内部,关注的是点。而可观测性关注的是应用本身的状态,是对系统的一种自我审视,强调从内到外,站在宏观的角度去聚合分析各种指标,不仅了解分布式系统所有链路的运行状况,还能在多指标同时发生问题时知道什么是因,什么是果,让工程师“理解”系统发生的一切行为,关注的是点线面的结合。
关注时间不同
监控更加注重问题的发现与预警,关注软件交付过程中以及交付后的1到2天,也就是我们常说的“事中与事后”。而“可观测性”是要对一个复杂分布式系统所发生的一切行为给出合理解释,关注的是研发与运维的全生命周期。
目的不同
监控是告诉我们系统在什么时间、什么地方、发生了什么问题,仅提供对已知问题或故障的答案。而可观测性是为了告诉我们那里为什么发生了问题,还允许工程师提出新问题。具备可观测性的系统,工程师既可以直观的观察到系统的整体运行状态,又可以轻易深入到系统运行的各个细节角落。在正常运行时,能对系统进行评估,提供操作建议,在发生故障时,可协助工程师快速理解、定位和修复问题。
监控与可观测性又是相辅相成的,监控是可观测性的一项基础设施和手段,监控是可观测性的子集,抽象如下图:
三 我们做了什么
分享下高德打车在探索可观测性系统建设过程中的一些具体实践,交流学习。
1 统一日志
首先对日志进行了统一治理,日志事件(Logging)是可观测性的三大支柱之一,当应用数上百,微服务数上千时,各应用的日志还任由开发人员根据自己喜好随心所欲的打,可能会形成一场噩梦。例如五花八门的格式、级别、分类,甚至于error和info都混杂在一起。我们将日志统一归为三类:监控日志,业务日志,错误日志,并封装提供专门的日志sdk,将“有效”的日志进行统一管控,还能间接达到控制成本的目的。
监控日志
监控日志只用来做监控,和其他日志进行区分,输出到一个单独的滚动文件里。
监控的原则是用来发现问题,而不是用来定位问题,要定位具体的问题,需要更详细的日志,通过监控日志中的traceId去关联其他内容即可。
监控日志统一以monitor开头,业务较多时,也可分多个,如monitor-biz1.log, monitor-biz2.log。监控日志分隔符固定用竖线 | , 监控指标成功失败统一归类为 success,fail (业务失败),error (接口失败)。耗时逻辑统一在sdk中实现,删除原代码中遍地存在的 long start=System.currentTimeMillis()。
统一监控日志还有另一个好处:当开发人员看到调用监控日志api的代码,会自然而然引起内心的重视,明白这是用来做监控的,我不能随意修改,避免不同开发人员协作时误改代码而导致监控错误。
sdk伪代码:
//定义key值,标记起始时间
MonitorLog mlog = MonitorLog.start("access", "url", "httpcode", "bizcode");
try {
//doSomeThing1...
//标记start到something1 做完后的时间
mlog.addTimeScope("time1");
//doSomeThing2...
if ("成功") {
mlog.success(url, httpStatus, response_code);
} else {
mlog.faild(url, httpStatus, response_code);
}
} catch (Exception e) {
mlog.error(url, httpStatus, response_code);
}
业务日志
这里的业务日志并不是指代码中开发人员随意打出的 log.info(...) ,而是指专用于定位业务问题,根据自己的业务特点,经过认真规划,打出的需要统一收集、存储和分析的业务相关的日志。
含关键信息,非关键信息,附加信息:
关键信息是业务流程中的重要标识,一般会建立查询索引,比如高德打车的订单ID,用户ID等。
非关键信息一般为业务日志描述,如“用户下单成功”,非关键信息可不建索引。
附加信息一般为业务流程中的附加信息,如“订单状态”,“订单标记”等,可不建索引。
错误日志
错误日志也进行格式统一,方便对异常的全链路分析和追踪。格式举例如下,如果某一项没有数据,会使用'-'进行占位。
2 全链路追踪
分布式全链路追踪(Tracing)是可观测性的第二大支柱,全局唯一的TraceId利用阿里中间件鹰眼Id的现成解决方案实现,保证了在整个链路的唯一性,然后解决掉在分布式调用链路中,同步改异步丢失traceId的问题,该traceId会同时在监控日志,服务日志,和错误日志以及其他日志中透传并记录,traceId持续的传下去,就是给整个请求链路打上了标记,链路上涉及的所有应用日志收录到阿里云SLS,接入阿里云api,通过api拿到所有应用的日志,通过TraceId就可以还原这次请求的整个上下文。
市面上有很多 APM 厂商,监控社区也有很多开源的链路追踪系统均可采用。
3 监控治理
这一阶段我倾向于称作是对可观测系统第三大支柱(Metrics) 的实现,是监控的梳理、补全优化阶段。“巧妇难为无米之炊”,如果基础监控项都覆盖不全,何谈可观测性。
这里我把监控归类为5个领域,如图:
醒一下,监控体系建设没有银弹,任何值得解决的事情都需要为之付出努力,不要幻想有一种工具能一下子解决你所有的监控问题。
再提一个监控建设的反模式“勾选式”监控。就是按照各种文档和要求,把各种监控工具都用上,然后就开始自嗨的认为自己的系统就会健壮无比,高枕无忧,这就是典型的“勾选式”监控,为了使用而使用,不会有好的效果。
分类介绍下上图监控体系的5个领域:
基础设施监控
首先是对于机器和操作系统环境的各项基础指标监控:cpu,mem,load,io,磁盘等,相信任何一个成熟的监控平台都会具备这项基础能力,不再赘述。
中间件监控
各种中间件的使用是分布式系统的重要元素,对于中间件的监控要遵循各个中间件的监控规范,推荐使用中间件自己的日志,指标模板等,不必重复造轮,口径统一也会减少沟通成本。
应用&业务监控
应用监控统一归纳为请求量,耗时,成功率三类,称为三大黄金指标:
请求量,含QPS、TPS、QPM、TPM等,其中分钟级指标必备,秒级指标在核心链路中也是必备,秒级指标可以探查到瞬时流量洪峰,在核心链路中是需要重点关注的。
耗时,不能只是平均耗时,还有要TP99,max等,平均耗时更多的是反应一个趋势,开发人员必须要关注TP99,只看平均耗时会隐藏掉诸如毛刺等很多问题。
成功率,包含接口成功率和业务成功率,接口成功率即请求该接口正常返回即认为成功,反映的是请求链路的问题。业务成功率是该接口的业务逻辑成功失败,反映的是业务的正确性,这是两个完全不同的指标。错误日志的监控,在此也归类到成功率的监控中,也是一个不可或缺的重要指标。
将应用监控的各项指标进行统一,一方面可以方便的查漏补缺,按照应用和接口list,挨个检查,有则完善,无则补充,另一方面可以减少沟通成本,不同的应用指标统一后,也降低了跨应用排查问题的复杂度和困难度。
业务监控是不同开发同学基于自己的业务日志建设而来,应包含业务的量级监控,趋势监控,还有各种转化率,转化漏斗的监控,很多问题单靠量级和趋势是发现不了的。业务转化率和转化漏斗是相对复杂的逻辑,且此类数据的报表一般都是BI做的T+1报表,及时性不够,缺少实时的转化率和转化漏斗监控,会让我们漏掉很多问题,问题发现时往往已经过去很久,此类复杂业务指标监控可以基于flink一类的流式计算来实现,即使做不到实时,能做到准实时,分钟级,小时级作用也是很大的,是对业务指标监控的重大提升。
业务监控这里不得不提场景监控,不同场景流量的规模是完全不同的。比如同一个微服务接口被不同的业务场景调用,只对接口级别的指标进行监控的话,流量小的场景错误数量很容易被流量大的场景错误量所淹没,在异常发生时,监控不报警,所以业务监控要做到针对场景的细分,可以指导我们做精细化的控制。
资损监控
应用和业务监控指标正常,不代表服务就是正常的。数据的正确性校验,最终一致性校验,资金安全问题同样是很严峻的问题,很容易被忽略。数据监控和资损防控能力也应是监控必备的能力,尤其是大促期间,上线各种促销补贴,促销活动和玩法,对资金安全提出更多挑战,防止用户/平台/服务商的资金损失,是对我们服务的基本要求。涉及数据核对,资损的防控一般都会涉及多方,因为要多方对账,一定要充分沟通,重要的资金风险场景都要覆盖到,监控时效性做不到实时的话,准实时和离线小时级是要必备的。
监控大盘
有了各个应用准确的监控项做基础,还需要建立核心业务链路的监控大盘。大盘有技术指标维度的,还要有业务指标维度。大盘的指标摆放遵循:秒级指标,分钟级指标,成功率,下游依赖成功率,耗时,下游依赖耗时等。layout提前设计,不能太宽松也不能太满,一行2-3个最好,趋势图和表格要共存,趋势图在数据源太多时展示同环比会很难看。
监控降噪
监控不能只是一味的增加,而不去保鲜,那是滥用,会产生很多恐怖的可能性。高德打车业务亦是如此,随着业务的发展,新老监控达到一定的量级,有些指标已经年久失修,数据不准仍每天报警,钉钉消息和短信数量爆炸,动辄未读99+,已经对工程师造成严重干扰。
降噪的原则是每个报警项都应该是可执行的,报出来就是需要依靠人的智慧来作出反应,而不应是机器人或脚本去自动回应。如果报警信息不能指导人的行动,就是噪音,浪费精力去关注。
监控降噪有2方面内容:
监控的名称语义要准确,见名知意,光看名字就能迅速知道是哪块业务出的问题,节省时间,方便值班人员周知相关人员。特别是一些url类的监控,已知的url要尽可能用到翻译,很少有人记得清这个url是干什么的。
中间件类的监控项名称中最好包含中间件的名称、类型、以及应用或业务名等。如:中间件_RPC_生产者/消费者_类别(成功失败汇总/耗时/错误码等)_应用名。
通知渠道
报警要有级别概念,根据指标核心程度,紧急程度,要区分不同的渠道,高级别监控指标要有短信或电话报警,短信和电话报警不宜过多,紧急程度不能无脑P0。
4 指标关联、拓扑、可视化
这一阶段我称作是对系统整体可观测能力的实现,目的是要能“理解”系统的一切行为。
前面3点做完了,你可能还会遇到很多类似的尴尬问题:监控系统显示为“正常”,但是我们的客服却不断收到客诉,甚至业务系统已经不能正常工作了,另外一种情况就是你已经发现监控各种在报警,却没办法告知哪块业务会受到影响,哪里会不工作,在规模化微服务之后,你可能连宏观的关联关系都发现不了,更别谈对系统行为的“理解”。这就是在当今云原生时代下的大型分布式系统中,可观测性相对于传统监控要解决的问题。
单纯的指标集监控可能会是一个不成体系的状态,在这种状态下,工程师衡量系统的运行状态,多是靠一些零散指标,或是靠一些元老级工程师通过自己经验,从多个指标里模糊构建出业务全局状态,盲人摸象,是看不清全局的,而这些经验也往往是不可复用的。更合理的做法是站在创造者的角度去探究如何让系统正确的展现自身的状态,通过技术手段建立系统监控的可观测性,既能从微观角度去看一个请求的完整链路,又能从宏观角度去分析问题,“看清”系统运行的全面状态,降低经验门槛和不确定性。
有效实施可观测性的第一要点就是要拆分指标,建立指标关联和拓扑,方式有很多,这里参考OSM数据分析模型法的方式,将监控指标分层进行拆解,细化到可落地执行的指标细项。
一级指标(主要为北极星指标)必须是全部认可、衡量业绩的核心指标。需要所有人理解、认同,且要易于沟通传达,比如下单量,完单量。
二级指标是北极星指标的路径指标。北极星指标发生变化的时候,我们通过查看二级指标,能够快速定位问题的原因所在。
三级指标是对二级指标的路径的分析。通过三级指标,可以高效定位二级指标波动的原因,这一步也会基于历史经验和拆解。
做监控指标的拆分并不是要求像OSM那样严格的按照3层去拆,只是借鉴一个理念,先整体的看业务全局,结合产品目标,业务链路,拆分出可执行,都认可的一级指标,以高德打车业务为例,最终定义出一级指标是下单,绑单,完单,支付:
对一级指标建立监控,建立量级和转化漏斗的多维度指标,如下单量,绑单量,下单量同环比,下单量趋势,业务转化漏斗绑单率,完单率,支付率等。
接下来选择一级指标“完单量”为例,再继续进行二级指标的拆分,先分析理清完单依赖的下游业务,通过趋势图和表格多种形式汇总展示。
下游依赖的二级指标拆分完成后,继续向下追溯,将下游依赖的内部依赖继续拆分,拆分出3层甚至4层更细粒度指标,指标继续拆分下钻,最底层可能就是各个依赖系统的基础监控指标(cpu,mem,load,网络,宿主机等)。
指标关联和拓扑建立完成后,就要对指标实行可视化能力,采用的方式多是一些监控大盘和图表,拓扑图等形式(监控大盘建立原则参考监控治理部分)。关联关系通过线、网、箭头交织在一起,再根据关联关系对链路流量进行染色,当相关指标发生报警时,就可以根据trace串联出完整的调用链路,定位到相关的异常报警和业务影响。
可观测性监控问题排查过程
当监控具备了可观测性能力,就可以大大提高问题发现和定位的效率。排查起问题来就会变得像医生看病,由内到外,由微观到宏观,通过CT等技术穿透身体各组织,将内外部整体的情况以图像的方式清晰展现,医生做出总体的诊断,直达病灶。
1)发现问题
当一级指标发生报警时,就是告诉我们,出问题了,这次以“下单”举例,比如收到了下单耗时增加的预警,开始接手去定位。
2)定位问题
如果一级监控指标下单发生了报警,那么它依赖的二级指标一定会发生波动。
比如下单的耗时tp99升高,观察下单依赖项,是下单依赖的二级指标“数据服务”耗时同期发生波动。
要定位到最终原因,还需收集更多指标信息,继续下钻数据服务的下级指标,是应用数据库中间件insert耗时增加,排查后发现超时现象都发生在同一台服务器,继续跟踪该机器基础指标监控,该机器所在宿主机load升高导致,继续跟踪,是该宿主机网络设备出现问题导致。
3)解决问题(止损)
问题定位后,对问题机器进行下线置换等手段,及时止损,耗时恢复。
4)沉淀预案
问题定位、解决完成之后,期望把处置的经验沉淀下来,这样就形成了预案,又多了一项保命符。
故障防御能力建设
当系统的可观测性模型越来越细致,越来越精确,便可以催生出许多自动化,智能化的决策能力,辅助上层做出及时有效的决策,指导我们做精细化的控制,解放人工生产力,这种能力我称之为故障防御能力,如图:
1)变更防御策略编排
监控治理完成后,维度覆盖全面,就会多线上的各项变更纳入管控,这里将变更归类为业务类变更和运维类变更,详细如上图。针对不同的变更分类,可以指定不同的监控手段来防守,比如运维类的扩容、缩容,不涉及到业务变更,在变更完成后,我们只需要对OS指标监控,应用的指标监控进行核对即可。针对代码的变更,在发布部署后,除对基础的os指标,应用指标核对外,还需要对相关的业务指标进行核对,以及涉及的资损指标监控。自定义各种编排策略,在不同分类的变更发生时,自动执行对应的监控手段。
2)变更管控
收录不同分类的变更,自动识别,自动打标,当发生变更时,可以获悉准确的时间点,自动周知关注人。
3)实时巡检
对各项基础设施指标自动化巡检,及时发现问题,自动周知。
4)主动防御(故障自动定位)
当具备了可观测性,就有了全链路的关联追踪能力,发生故障时,把相关的变更、告警做分析推导,自动给出根因推荐,还可以对一些核心指标做重保,当重保指标发生报警时及时作出问题推荐,产生处理工单,通过稳定性AI智能交互机器人持续跟进,可在钉钉群一键接手,形成处置闭环。对于可自行补偿的问题,自动执行补偿策略,故障自愈。
5)全域高精可观测性
所有的智能化决策能力,都是建立在系统高精的可观测性基础之上,而可观测性,又是基于监控,日志,和全链路追踪三大支柱而来,最终形成无人值守故障防御能力。
四 写在最后
最后做一个小结,在云原生时代,运维自动化和智能化的大趋势中,系统可观测性是稳定性建设的最基础一环,是稳定性保障武器库中的那把“霜之哀伤”,完善的可观测体系可以帮助我们屏蔽系统的复杂性,使系统整体的运行状态清晰可见,在故障防御和排查方面发挥了巨大的作用,增强对系统的信心。
稳定性建设又是一个体系化的工程,不可能一蹴而就,关键在于持续不断的完善,更脱离不了业务,高德打车业务的稳定性建设也是在业务不断发展过程中逐步探索建立起来,2020年多个节假日出行高峰向我们提供了最好的“练兵场”,“试金石”,系统平稳度过。
当然稳定性建设的打法是多种多样的,但目标都是一致,希望本文对大家有些许帮助。
CIO之家 www.ciozj.com 公众号:imciow