可观测性(Observability)是近年来备受关注的话题。那什么是可观测性?别急,让我们先从一个常见的场景开始:
你是一个一线开发同学,在某天上班路上收到了一个电话报警,提示某个接口的错误数超过了阈值 30。得益于公司监控团队做的所谓 chatops,几经周折后,你终于在 IM 中打开了对应的监控图表,发现当前的错误数似乎比之前多了一些。
作为服务开发者的你,昨天晚上部署了一个新版本,并且依赖的服务好像也做了变更。你开始猜测这个报警是否与你昨晚的上线有关,但怎么也回忆不起来昨晚依赖服务的变更内容了。
你的组长打电话过来询问报警的情况。搞不清状况的你只能回答”我需要看一下”。你打开电脑连上热点并登录上了机器,tail -f xxx.log | grep -E 'error|timeout|code=9527'。一通猛如虎的操作,你发现了问题所在,是你依赖的另一个服务延迟过高导致。和你的上线无关,和昨晚变更的依赖服务也无关。
上述这个场景,很多同学都遇到过。我们从中会发现一些问题:
缺乏进一步分解和深入分析的能力:得到监控产出的图表后,无法进行进一步的分解,我们不得不跳出当前上下文,使用如 tail、grep、tcpdump、strace 等工具进行问题追查。
复杂的微服务架构难以定位问题来源:因为复杂的微服务架构,无法确定问题源自哪里,是服务自身还是依赖的服务出现问题。
难以确定合理的报警规则:不能确定诸如 if len(error) > 30;then alert() 这样的行为是否合理。
排查问题依赖我们的历史经验:例如 9527 这样的 code,是上一次故障添加的,用于识别某类错误,但这类错误可能永远都不会再出现,只是不知为何这个数字在我们脑海里印象颇深,出于短期的记忆,顺手作为了过滤条件之一。
这些问题如何解决?需要依靠可观测性。可观测性在计算机领域目前仍没有标准的定义,但已经有了一些共识:如果你能从外部,理解一个系统所处的任何状态,这些状态不需要是预定义的(例如 9527),它们可能出现过也可能从未出现。当新的状态出现时,也不需要你重新埋点、发布新代码,那么我们说这个系统就具备了可观测性。
基于上述对可观测性的描述,我们从几个方面简单比较所熟知的监控与可观测性,以便大家能够更直观地理解它们的区别:
监控关注聚合值,可观测性关注明细:在传统的监控中,通常会采集和展示聚合后的指标值,如平均值、最大值、最小值等,用于判断系统的整体状态。而可观测性更注重收集和展示明细信息,比如原始日志、指标的分布情况等,使得开发人员能够深入了解每个细节,从而更好地发现问题和优化系统。
监控使用阈值,手动或自动与阈值进行比较,或依据历史经验或者是早已经过期了的 run book 来猜测当前系统的状态。可观测性因为拥有明细信息,所以倡导和鼓励用户主动去探索和了解系统,从而能更准确地发现问题。
监控面向有经验的工程师,可观测性面向所有工程师。
总的来说,可观测性的目标是为了让我们更好地了解系统的运行情况,从而能够更快速地发现和解决问题,提高系统的稳定性。它强调的是全面的、详细的数据,鼓励用户主动去探索和发现,而不仅仅是被动地接收那些我们自己都无法确定阈值的报警通知。
上一节我们简单描述了一下可观测性优于监控的地方。那如何实现可观测性?可观测性期望尽可能多的保留请求上下文,以便探索导致故障(可能是历史的也可能是新的)的环境和细节状态。因此可观测性在信息的丰富程度上,要求比监控高很多,需要用户暴露更多的信息(例如丰富 Metrics 的 Label),但这样一来,用户的成本可能就控制不住了。
画外:说来说去你不就是要加钱么?
作者:秀儿同学,请你先坐下。
如果按照一些 SAAS 厂商的推荐做法,上报几十几百的维度,每个维度下不限制基数,的确可以达成可观测性的先决条件。但有 2 个现实问题:
上报如此丰富的数据,用户成本将会爆炸性地增长。
现存的存储解决方案,很难能扛住如此高维度+高基数+大量级的数据。
画外:你就不能自己实现一个么?
作者:保安在么,请秀儿同学出去。
除了一些 SAAS 厂商倡导的 high dimensionality, high cardinality 论调外,开源届更倾向于采用“曲线救国”的方式,通过关联当下主要的观测信号来实现可观测性。这些主要的观测信号包括:Metrics(指标)、Traces(分布式追踪)、Logs(日志)等。关联论期望关联 Metrics 的高层次抽象 + Traces 的跨服务的上下文关联 + Logs 暴露最详细的 Human-Readable/Acceptable 信息的形式,达到可观测的目标。
上一小节提到实现可观测性的两种路径,那在滴滴使用哪种方式?
答案是结合这两者,以平衡成本、效率和实现可观测性的目标。在实现上,我们改造了日志采集和 Metrics 采集的方式,对低基数和高基数维度进行切分,分别存储到不同的后端存储中,并建立关联关系。对用户暴露其关心的日志原文、traceID 等信息,从而实现可观测性。
具体来说,对于日志采集,在采集端实时分析日志生成监控曲线的过程中,会按照给定的周期,采样上报一条日志原文及其与监控曲线的对应关系。对于 Metrics 采集,需要用户调用埋点代码时传递额外的参数,告诉我们希望采样保存的维信息,这个额外维在生产环境中一般会被设置为 TraceID,它不会出现在 Metrics 曲线的 Label 中,我们每个周期采样上报一条额外维的信息,及其和监控曲线的对应关系。
可观测性不仅仅需要在技术层面考虑,更要完善产品以帮助用户从监控到可观测性的升级。下面,我们将介绍几个常用的场景,并结合前文所述,深入感受可观测性带来的便利性和可探索性。
如果配置的策略发出了报警通知,可以直接在 IM 中查看你最熟悉的日志原文,基于日志原文进行下一步的决策,无需登录机器,无需 tail、grep 等。
图1: 报警现场关联日志原文
只是在报警时刻使用还不够,还可以在看图时下钻日志原文,我们已将提取的日志原文进行简单清洗,当识别到 TraceID 时,可以直接跳转到 Trace 平台进行上下游服务的排查:
图2: 曲线看图关联日志原文、TraceID
通过建立 Logs、Traces 和 Metrics 这几个观测信号的关联,这套内部称之为 MTL 的架构和产品,在滴滴的可观测体系中发挥着重要作用,使得开发人员和运维团队可以更加了解其系统的运行状态,从而更准确地发现问题和进行故障排查,这套系统也得到了众多用户的认可和正向评价。希望通过这篇文章,能为大家提供一些经验和启示。
云原生夜话
你们公司有在做可观测性吗?是如何实现的?欢迎在评论区留言,如需与我们进一步交流探讨,也可直接私信后台。
作者将选取1则最有意义的留言,送出滴滴定制多功能跨包,9月19日晚9点开奖。