背景
日常工作中,我们可能会经常遇到如下情况:
2020年之前,团队每当遇到如上问题的时候,大家经常是心头一震,心里发慌。wocou!发生了什么。要是已经下班或正在休假,还得掏出电脑,在经过没有预期的尝试与排查后,给领导一个故障范围和问题原因,有时也只能定位到大概范围。甚至会出现「莫名其妙坏了,莫名其妙好了 」的尴尬局面,事后很难复现。
大部分故障与问题都是用户投诉或老板@才发现。问题发现后,不能快速定位问题,不能做到及时只损。以微博会员20年临时头像的故障为例,故障从反馈到最后临时解决,花费了将近2个小时。这是微博会员团队近2年来最严重的故障。最后确定故障根因是MC存在热点大Key,导致带宽打满,最终影响了用户使用。
同时微博会员是一个成立了近10年的业务团队。人员与业务分分合合,依赖关系错综复杂。没哪个人能完整知道所有服务的链路细节,新人上手难。20年团队也在做各种变动,基础服务升级重构、PHP版本升级、Go语言技术栈转型、服务全面拥抱k8s等等。频繁的变动也就意味着会滋生新的问题,新问题难免会隐藏、无法被及时发现。
这一年,团队痛定思痛。我们都希望能有更趁手的工具,让开发人员更关注开发本身。希望90%的问题能通过报警主动发现而非用户反馈。希望问题从发现到定位耗时缩短至15-30分钟,缩短MTTR。希望服务RT降低30%。
正因如此,也就有了本文。
发展
会员团队服务质量保障的发展历史我大概分为了三个阶段。
第一阶段:(20年前)ELK+Grafana+Graphite+(各种时序数据库)
如上图所示,ELK+Grafana的方案基本已经成了事实标准一样的存在。尤其对于中小团队或者研发成本不是非常充裕的公司来说(研发成本宽裕的公司都有自研的方案,暂不做讨论)。微博的各团队基本也都是这套方案或这套方案的变种。
这套方案本身没什么问题,但由于微博内部业务方众多,互不相通。不少团队都自行维护了一套自己的ELK+Grafana。由于没有统一调控,各自数据模型不统一,数据互相之间像是一座座孤岛。
每次排查问题要需要打开N个Grafana Dashboard,还要在每个Dashbord中一个条件一个条件的筛选。时间就这样一点点流逝了。下游依赖报警相互独立。若是碰上服务异常的连锁反应,完全无法判断是先有鸡还是先有蛋,告警反倒成了拖累。监控覆盖度不足,监控体系不统一,都是需要解决的问题。
第二阶段:(20年中) 引入APM工具,初探可观测性
有问题就要解决问题。监控覆盖度提高,快速定位性能瓶颈,成为了当时首要解决的目标。经过调研与权衡,最终我们决定引入APM工具—。SkyWalking与其他APM工具相比,功能对PHP兼容相对完善,接入无需代码侵入,社区活跃度高。
skywalking
apache • Updated Aug 31, 2023
引入初期,团队成员对新工具还比较新奇,都是第一次接触Trace的概念。SkyWalking成为了当时的救命稻草。随着Trace概念的引入,过去需要主动日志埋点,甚至被遗漏的场景随之被弥补。性能瓶颈、项目依赖、拓扑图都能得到很好的展示,大家与SkyWalking度过了几个月的蜜月期。
不过在SkyWalking的使用过程中,也发现了一些问题。
- 功能对非Java技术栈的兼容不够友好。前文说到的功能支持相对友好也只是相对来说。毕竟SkyWalking是Java生态的工具。其他语言功能支持都进行了阉割或本身就无法支持。Dashboard大部分不可用。
- 本身Java开发,告警等功能不完善,二开成本高,难以与内部工具集成。
- SkyWalking 部署、存储、维护成本高。
- SkyWalking PHP 扩展功能支持度不完善。比如在微博内部大量使用的与memcachedmemcached • Updated Aug 29, 2023最初并没有支持。没办法,只能fork一份自己维护内部版本。当然后来也将Memcached与Yar的支持贡献给了官方。yarlaruence • Updated Jul 28, 2023Support memcached componentUpdated Apr 17, 2020新增 Memcached YarUpdated Aug 16, 2021
- SkyWalking PHP 扩展性能表现不理想。平均性能损失接近20%-50%。尤其在高并发的情况下性能下降的更加明显。刨除PHP本身进程模型的限制。主要还是最初选择的实现拦截机制效率比较低。。最新扩展已由Rust重构、且拦截机制已优化开了php的扩展之后,cpu压力明显上升,差不多多用了20%Updated Nov 3, 2021。skywalking-phpapache • Updated Aug 30, 2023
- Metric、Log、Trace 之间相互独立。从经验来看,这三种数据并不是完全孤立的,相反,这些数据之间息息相关。
- 引入APM工具后,我们排查问题的后台变得更多了,与之相关需要维护的服务也是越来越多。对于业务小团队来说成本也越来越高。考虑到如果随着后续发展要引入更多的新工具,每次都需要承担相应的改造成本。
后面统计发现大家使用SkyWalking最多的只有Trace UI。同时也因为1、2、3、4、5的问题无法解决。最后完全抛弃了SkyWalking。以私有协议了重写一个内部扩展,优化了4、5的问题,用ClickHouse替换了ES,Trace存储成本下降了10倍,用Jaeger替换了SkyWalking。
第三阶段:(如今)
受到 勇攀监控高峰 | EMonitor 之根因分析 文章的影响。结合这段时间的经历。当时我就在想,有没有什么解决方案,可以将Metric、Log、Trace 串联统一管理。自动关联并分析相关数据,尽可能实现根因分析。最好成本也要相对低廉。换句话说,我想实现一个包含EMonitor核心功能且低成本的EMonitor。
同时深感上报收集处理Metric、Log、Trace 数据的服务还是太多了。总结了一下这个过程。无论是什么数据。基本都是数据收集、数据清洗、数据分析、数据存储这四个步骤。那如果我抽象出这四个过程。岂不是可以统一越加越多的数据收集服务。我认为这应该是业界的通病,既然是通病,那就应该已经有类似问题的解决方案了。
抱着目标、带着疑惑在Github冲浪的时候,我发现了 OpenTelemetry 。简直和我的需求一模一样。伴随着对OpenTelemetry项目的深入了解。可观测性的概念也逐渐映入眼帘。
就这样,基于OpenTelemetry,让团队服务具有可观测性的计划提上了日程。团队可观测性的初探,也就这样开始了。
可观测性(observerbality)
「可观测性」(observerbality) ,是一个最近几年开始在监控社区流行起来的术语,可观测性的提出最早来自于 Google 著名的 SRE 体系和 Apple 工程师 Cindy Sridharan 的博文 Monitoring and Oberservability。
- 那么可观测性到底什么是呢?
- 可观测性和我们传统的监控有何不同呢?
- 如果我们已经有了传统监控手段,为什么还要再投入成本做可以观测性相关的探索呢?
别急,接下来都会一一解答。
首先要明确一点,
可观测性并不等于监控、可观测性并不等于监控、可观测性并不等于监控
可观测性是一个包含了监控的更大的集合。引用一下 Baron SchSchwarz 大佬的定义:
监控告诉我们系统的哪些部分是工作的。可观测性告诉我们那里为什么不工作了。
首先他们的关注重点不同,监控主要关注具体指标的变化和报警、关注系统的失败因素、关注业务指标异常。关注的是结果数据。
监控通过一些外部因素或者与服务相关的指标来侧面反映服务的健康状况。比如SLA、可用性(3个9、4个9 ...)、系统容量(QPS、TPS ...)、延迟(P99、P90 ...)等。再比如机器性能指标、资源指标、服务QPS,服务状态等等。这些大部分指标都是与运维息息相关的,传统监控服务大部分也都是在运维团队手中。这里我把监控的生命周期简单的总结为,指标上报、指标计算、指标展示、指标告警。监控只是单纯的对指标数据的管理。至于是具体什么原因触发的指标异常,它并不是很关注,也力不从心。各指标之间相互孤立,各自为战。
同理,传统监控很难定位到需要接口优化的瓶颈点在哪。容量评估时,往往只能依靠开发同学的经验。更最重要的是,我们不能保证指标、日志、告警等需要监控的区域都能被覆盖到,常常出现亡羊补牢的状况。
另外单一指标也存在一定的欺骗性,比如某个业务的下游依赖已经不再健康,但是因为有兜底方案或暂时不是业务核心接口,所以在整体的服务质量监控中并不能明显的体现,那么这些未发现的不健康指标都有可能成为未来的隐患,随时暴雷。
就像我们身体出了问题,我们只能表象的知道腰痛了。但是具体是什么原因引起的,我们无从得知。可能是单纯的拉伤、可能是腰间盘突出、还可能是风湿等等,进一步确认就只能去医院,通过更精细的仪器,结合医生的经验去帮我们诊断。这些都是无法直接通过表象推断的。
总结一下,监控是告诉我们系统在什么时间、什么地方、发生了什么问题,仅提供对已知问题或故障的结果记录。
而可观测性则更关注的是服务本身的状态。是系统对于自身的观测。
可观测性的立场是站在被观测对象(也就是目前运行的应用)之上,他的出发点是被监控的对象。从内部出发,让我们收集的信息更为详细与完整。通过内部数据与外部数据的关联与聚合。可以让我们更清楚的知道服务当下的状况。更清楚的知道当不同的指标异常,到底是什么因素引起的。同时也能反推某个指标异常会影响哪些服务。让我们更好的掌握服务的每一处细节、以便将以前松散的指标相互串联。
同样假设我们身体出了问题,我们提前在身体内植入了纳米机器人(client sdk),这些纳米机器人会时刻采集我们身体内部的各种指标(Metrics)。随时进行精细的健康检测。当我出现腰痛的时候,我们可以根据纳米机器人上报的数据,使用所关联的app(APM)提供的智能分析报告(根因分析),我们就可以很清楚的知道我们的身体发生了什么。是否仅仅只是肌肉拉伤、腰锥是否正常、尿酸是否增高。当我们觉得指标信息不够用时,甚至可以指挥纳米机器人对问题器官进行小型x光检查。我们便可以快速的针对性的进行调整。只有遇到疑难杂症时,才会去医院请教医生。大大缩短了排查效率。同时还可以提前根据身体指标变化预知健康状况(异常检测、AIOps),反推会影响哪些器官,提前进行健康管理(性能优化)。
可观测性建设就是为了告诉我们哪里为什么发生了问题,同时可以提前观测服务的整体状况,提出新的问题。具备可观测性的系统,开发同学既可以直观的观察到系统的整体运行状态,又可以轻易深入到系统运行的各个细节角落。在正常运行时,能对系统进行评估,提供操作建议。在发生故障时,可协助开发同学快速理解、定位和修复问题。
可观测性三大支柱
我们看一张 CNCF 的云原生可观测性家族的开源图谱。
经过社区的不断分化分类,逐渐细化成了五个大的方向,一年前是三个,半年前是四个,分别是 Monitoring(Metrics)、Logging、Tracing 以及最近加入进来的混沌工程(Chaos Engineering)、Continuous Optimization。这五个分支共同组成了可观测性与分析的大家庭。他们各自负责自己擅长的事情。彼此协作。
本篇文章主要着重介绍的是其中前三个。Metrics、Logging、Tracing。来一起看一下它们分别是负责什么的。
Metrics,是一种聚合数值,用于描述服务的各种指标。可以观察系统的状态和趋势。此数据模型是三个数据模型中占用空间最小的。但展示的信息有限。 Metrics包含了传统监控的相关,但不限于传统监控。比如我们常说可用性(3个9、4个9 ...)、系统容量(QPS、TPS ...)、延迟(P99、P90 ...)等,都是各种数据聚合的结果值。并且我认为指标不应该仅仅局限于这些系统指标,还应该包含各种业务指标、通用指标等。不要因为传统监控的原因就把Metrics限制在系统指标中,又或者觉得业务指标等不算Metrics。Metrics直译就是指标。不应有差别对待。至于是否影响了服务质量,哪些指标是原因,哪些指标是结果,这些都应该交给根因分析去判断。
Logging,展现的是服务运行过程中产生的事件或者服务在执行的过程中间产生的一些日志,该数据模型可以详细解释系统的运行状态和事件,但是存储和查询需要消耗大量的资源,日志通常是由大量的非结构化的信息组成。所以此数据模型的存储空间介于Metrics与Tracing之间。且保证日志的可读性也是影响问题排查问题效率的重要原因。
Tracing,追踪单个请求的进程,称为Trace,由组成应用程序的服务处理。该请求可以由用户或应用程序发起。分布式追踪是一种贯穿进程、网络和安全边界的一种追踪形式。Trace中的每个最小工作单元称为一个Span。此数据模型是三个数据模型中占用空间最大的。当然展示的信息也是最详尽的。
其实这些概念并不是新概念。不同厂商和开源社区早就已经有了大量的实践。像在可观测概念没有被广泛认可的时候,Jaeger就已经是trace分析届的top级别的项目了。日志有ELK的解决方案。Metrics也有 Prometheus、Influxdb、Grafana等。
可观测性更像是一种理念。不是我们要构建可观测系统,而是我们应该让我们的服务具有可观测性。
另一方面,我们在云原生可观测性家族图谱中可以看到,每个分支可以供我们选择的技术方案是非常多的。甚至即使是相同的技术方案也可能会有不同的实现方式。不同技术栈之间打通的成本也异常高。同时很多产品是和厂商绑定的。比如你用了阿里云的服务就没办法无缝迁移到腾讯云中。或者开源的Jaeger也没办法无缝迁移到Skywalking。就像健康码一样,每个省份、甚至每个市都不一样。虽然做的事情是类似的,但大家都在自己的生态下玩耍。底层不是一套统一的协议就无法互通,即使想互通也要做大量的兼容工作。增加了使用者的成本与心智。
那么,有没有什么什么办法解决这个问题呢?答案是肯定的。既然大家都在自己的生态下玩耍,那能不能某个有影响力的公司或组织维护一套标准,大家自愿遵守,就像秦国统一度量衡一样。基于这种思想,我们的主角OpenTelemetry诞生了。
OpenTelemetry
在讲 OpenTelemetry 之前还要必须再要提一下 OpenTelemetry 和 OpenCensus 两个协议。在OpenTelemetry之前,其实社区就已经发展出两个想要统一度量衡的协议了。它们分别都占据各自的半壁江山。
最初其实是没有统一协议的概念的,各大厂商和开源软件都是单兵作战。OpenTracing也正是在这个背景下由社区孵化,是最初想到要统一的项目。OpenTracing制定了一套平台无关、厂商无关的协议标准,使得开发人员能够方便的添加或更换后端的APM服务。其中遵循OpenTracing协议的产品有Jaeger、Zipkin等等。该项目于2016年11月被CNCF接受成为CNCF的第三个项目,CNCF的前两个项目都已经鼎鼎大名了,他们分别是K8s和Prometheus。不过看OpenTracing的名字就知道了,这个协议只是针对于Trace。最初也确实只是想解决trace问题的。随着社区的不断发展,很显然OpenTracing并不能满足所有用户的需求了,也就有了后面的事情。
前面提到过,对于可观测性来说,Trace只是它的一个分支。可观测性还有Metrics与Logging。OpenCensus项目最初目标并不是抢OpenTracing的饭碗,而是谷歌为了把Go语言的Metrics采集、链路跟踪与Go语言自带的Profile工具打通,统一用户的使用方式。但随着OpenCensus的场景进一步扩大,它不仅做了Metrics基础指标监控,还做了Trace的协议统一。不过这是正常的,毕竟分布式链路追踪的基础论文都是人家谷歌发表的。此时OpenCensus项目便跟OpenTracing项目有了竞争关系。
后来两个协议就一直在处于内耗和分裂社区的状态中并行。各位大佬和社区都看不下去了。开了个会就决定统一两个协议。并且加入Logging的数据模型。也就有了OpenTelemetry项目的诞生。
下表为各协议之间的对比:
标准 | 概述 | Traces | Metrics | Logs | 状态 |
OpenTracing | 2015年底发起,2016年被批准为CNCF第三个项目 | 支持 | ㅤ | ㅤ | 合并 |
OpenCensus | 2017年,起源于Google,项目负责人来自Google,Microsoft | 支持 | 支持 | ㅤ | 合并 |
OpenMetrics | 2017年,起源于Prometheus社区,项目负人来自Grafana,Gltiab | ㅤ | 支持 | ㅤ | 持续更新 |
OpenTelemetry | 2019年,由OpenTracing和OpenCensus合井而来 | 支持 | 支持 | 支持 | 蓬勃发展 |
什么是OpenTelemetry?
OpenTelemetry is a collection of tools, APIs, and SDKs. Use it to instrument, generate, collect, and export telemetry data (metrics, logs, and traces) to help you analyze your software’s performance and behavior.
OpenTelemetry是tools、api、sdk的集合。使用它来测量、生成、收集和输出「遥测数据 telemetry data」(metrics, logs, and traces 的总称) ,以帮助我们分析软件的性能和行为。OpenTelemetry项目提供了一个与供应商无关的实现。该实现可以将遥测数据发送到我们选择的任何后端服务。它支持各种流行的开源项目,如:Jaeger、Prometheus、SkyWalking、Elastic等。
可观测产品需要各种的遥测数据来进行驱动。一般来说,遥测数据都是由开源项目或商业供应商提供的。由于缺乏标准化,导致数据缺乏可移植性、同时用户还需要承担不同测量器的维护成本。也就导致了最初所说的大家都在自己的生态下玩耍的现象。
OpenTelemetry项目则通过提供了一个与供应商无关的解决方案来解决这些问题。该项目得到了业界的广泛支持,并得到了云厂商、供应商和开发者的支持。
OpenTelemetry为我们提供了:
- 每种开发语言都有一个与供应商无关的工具库,支持自动埋点与主动埋点
- 通用收集器(OpenTelemetry Collector)提供了多种部署方式,其中包括代理模式(agent)或网关模式(gateway)
- 一个端到端的实现,用于生成、发送、收集、处理和输出遥测数据
- 通过配置将数据并行发送到多个目的地的能力,数据自主可控
- 开放标准的语义约定,以确保收集的数据与供应商无关
- 能够并行支持多种上下文传播格式,以帮助随着标准的发展而进行迁移
- 兼容 OpenTracing 和 OpenCensus 协议
简单来说OpenTelemetry就像是普通话体系,其他的开源或私有供应商协议就像是方言。虽然方言之间互不相通,但是都可以先转换成普通话。普通话作为沟通的桥梁。并且也在不断完善普通话规范。为了提高沟通效率,各个民族之间也可以直接使用普通话。与此同时,为了普通话更好的普及,降低学习成本,提高效率,官方做了非常多的工具供大家使用。OpenTelemetry项目做的事情其实也都差不多。
OpenTelemetry不是什么?
OpenTelemetry不是像 Jaeger 、Skywalking、 Prometheus 那样的可观测后端应用。相反,它仅支持将数据导出到各种开放源码和商业后端。它提供了一个可插拔的体系结构,因此可以很容易地添加各种附加技术、协议和格式。更简单的说OpenTelemetry抽象了可观测性的完整生命周期。实现了与厂商无关的一个抽象层。至于如何处理遥测数据这是APM后端的事情,与OpenTelemetry无关。
如下是一张官方的整体架构图:
如下是一张官方的OpenTelemetry-Collector架构图:
由上面两张图可以看到,OpenTelemetry 抽象了数据流周转的生命周期。在各个生命周期中,OpenTelemetry都提供了对应的标准化的工具。也就是说,这些巨量重复的工作从此不再需要我们去关注。我们可以直接使用官方开源的工具。只有不能满足我们定制化需求时,我们才需要对某一个生命周期进行可插拔式的插件开发。如果是比较通用的需求,也可以先去社区中寻找有没有人已经做过了。众人拾柴火焰高。这些插件都被收录到 官方的Registry 中,方便我们直接使用。简直是保姆式服务。更为重要的是,只要是OpenTelemetry生态下的产品,使用者毫无迁移成本。
当然OpenTelemetry暂时也有一些问题。比如一些协议和工具还是测试和实验版本。OpenTelemetry Collector源码变动过大,迭代过快。显然 OpenTelemetry 还比较年轻,成熟度与覆盖度还不够完善。
但是这并不影响它的优秀。变动和迭代过快也正说明社区的朝气蓬勃。与此同时OpenTracing和OpenCensus两个协议均已经宣布停止维护转向OpenTelemetry。Jaeger Client sdk也已放弃维护转向OpenTelemetry Client sdk。各大云厂商如国内的阿里云、腾讯云、谷歌云等众多云厂商的APM应用也都做了OpenTelemetry协议的兼容。无论是从社区的态度还是各大云厂商的态度来看。OpenTelemetry无疑都将是未来可观测性协议的基准。现在暂时的问题只能说是瑕不掩瑜。
未完
既然已经有了正确的方向,那么接下来就是实施落地了。
在建设之初,我们总结了一些需要解决的问题与所面临的挑战。
- 如何快速地定位故障?
- 如何准确地评估容量?
- 如何动态地展示服务链路?
- 如何精准地优化性能?
- 如何相对智能地告警?保证召回率的同时提高准确率?
- 如何做到对业务无感知,接入成本低,性能损耗低。
- 如何做到一站式观测?
- 如何低成本(人力、存储、算力)实现 (重要)
- ……
那么我们是如何基于OpenTelemetry生态从0到1构建可观测体系解决上述问题的。过程中我们又踩过哪些坑,是如何解决的。以及现有成果和对未来的发展与思考是什么。限于篇幅的原因,这部分将在 微博增值团队可观测性探索与实践-实践 篇中着重介绍。本篇更偏向于前言与理论知识的介绍。算是入门介绍吧。
本人也是初学者,正在不断学习,不可避免存在理解不够透彻的地方。欢迎大家在评论区讨论。我也会随时修正完善文章。
延伸阅读
storage.googleapis.com
https://storage.googleapis.com/pub-tools-public-publication-data/pdf/36356.pdf