微博增值团队可观测性探索与实践-实践
微博增值团队可观测性探索与实践-实践

微博增值团队可观测性探索与实践-实践

Tags
可观测性
OpenTelemetry
APM
Published
May 23, 2022
Author

前言

前言与理论请参考 微博增值团队可观测性探索与实践-初探 。强烈建议优先阅读。

愿景

让开发人员更关注开发本身

整体架构图

notion image
 

服务应用

最上层是我们需要观测的各种服务。这里的服务不仅限于业务,还应该包括运行环境、存储、中间件等基础设施。换句话说所有会影响到服务质量的因素都应该被观测。可观测数据越全,代表后续可供根因分析的线索越多。在数据收集时,需要提前做好规划,保证数据之间的关联性,而非无脑堆砌数据。
将需要观测的服务大致分为三大类。第一类基础设施,如:物理机、云服务器、k8s、Serverless、DNS,交换机等等。第二类是各种资源依赖与中间件,如:MySQL、Redis、Kafka、Istio,etcd等等。最后一类是我们的业务应用,也是各位业务同学最关心的一个环节。一切可观测都是为了保障业务的可用性。

遥测工具(Client Library)

由于服务是多种多样的,我们需要收集的数据非常多。如此繁多的数据我们该如何处理呢?这个倒不用我们担心,社区早已经帮我们想好做好了。对于常见的基础设施、资源依赖与中间件,社区提供了相关工具 Registry 供我们开箱即用。如果在这里没有搜到也没有关系,各大云厂商、开源社区也在积极的配合生态建设。如果等不及或者存在内部自研的基础服务需要数据收集我们只需要按照规约按照提供的 sdk上报数据即可。这样相关自研的基础设施便可以快速融入生态当中,同时仅需开发所要关注的部分,节约成本。
业务应用遥测数据收集根据开发语言主要分为两种,一种是类似Java、PHP这种有运行时的语言来说,他们可以通过在runtime机制里无侵入的进行数据收集。对于Python等语言则可以通过sdk主动埋点的方式实现。
微博增值团队技术栈主要以PHP、Go为主。 接下来就以PHP与Go为例、讲一讲如果低成本地接入OTel(OpenTelemetry 缩写)生态。这两种语言也分别代表了无侵入与代码埋点两种数据收集方式。其他语言同理。

PHP (无代码侵入)

在说我们的解决方案钱,先说一下PHP OTel社区现状。社区目前提供的
opentelemetry-php
open-telemetryUpdated Nov 29, 2023
项目通过主动埋点的方式进行数据收集。目前仅支持PHP version of 7.4.x, 8.0.x or 8.1.x (版本过高),截止2022-11-27为止,该方案还处于Alpha状态。
增值团队内部项目众多,业务悠久。很多老业务都已经处于归档状态。即使是活跃中的项目,也因不同时期选择了不同的内部框架,代码入侵的方式是无法接受的。团队成员接入成本过高。
那有没有什么更好的替代方案且可以做到代码无侵入呢?
答案是肯定的,还记得微博增值团队可观测性探索与实践-初探中介绍的 SkyWalking吗?SkyWalking PHP 数据收集的方式是基于PHP扩展,原理是通过拦截 PHP runtime exec 函数进行数据收集。由于当时SkyWalking PHP官方扩展的一些问题,我重写了一个性能优化且私有协议的内部版本扩展。那么接下来我需要做的工作就只要把私有协议改为OTel协议就好。另外OTLP(OpenTelemetry Collector)是以gRpc进行数据上报的,由于PHP进程模型与扩展能力的限制,在一些高并发、极端网络场景下,会阻塞进程,造成性能问题,最终影响业务,这是业务不能接受的。在权衡过后,我们认为可观测性数据收集上报应属于旁路服务,可以接受一定程度的数据丢失,于是也支持了基于udp协议无状态数据上报。该扩展已在微博增值团队及公司其他业务线稳定运行,得到广泛验证。同时该扩展也提供高级功能,对外暴露了可以主动埋点的api供开发人员定制化使用。
补充:2022-11-27:最近重新完善该文章的时候发现社区又新增了一个
opentelemetry-php-instrumentation
open-telemetryUpdated Nov 29, 2023
PHP扩展项目,该项目以扩展的形式与opentelemetry-php项目相互配合。弥补opentelemetry-php项目需要主动埋点的缺点。opentelemetry-php-instrumentation 项目是通过代码主动注册被观测的方法,然后在PHP运行时自动生成链路结构,结合opentelemetry-php项目进行数据管理与上报,兼顾了成本与灵活性。不过目前opentelemetry-php-instrumentation项目仅支持PHP version 8+,且该项目状态仍未 experimental 状态。只能暂时观望了。

Go (代码侵入)

同样先说一下Go OTel社区现状。社区目前提供的
opentelemetry-go
open-telemetryUpdated Nov 30, 2023
项目与PHP社区一样,都是通过主动埋点的方式进行数据收集。
除了手动埋点外,Go其实也有无代码入侵的 Go HookWASMeBPF 三种机制选择。
我们内部最终选择的是官方提供的主动埋点的方式。
WASM与eBPF两种方式都属于实验性质。支持度与可用性都没有得到很好的验证。技术方案暂时还不成熟。
Go Hook方案与PHP扩展原理类似,都是在runtime层修改被拦截的方法,以达到无代码入侵。但是由于Go版本升级相对于PHP来说简单太多,而且大部分情况下业务方都是紧跟版本,享用最新版本特性的。那么就要求服务提供者要随时保证升级Hook代码以兼容最新版本,成本相对较高。更重要的也因为历史没有该方案的技术积累,在当时来说都属于不可控因素。
当时还有一个时代背景,增值团队正在推广落地内部的Go框架,恰好这部分工作我也在参与负责。在能保证所有业务方框架统一的情况下,代码入侵也不失是一种成熟且成本低的解决方案。对用框架使用者来说也是开箱即用,没有接入成本的。综合种种原因,最终我们选择了社区提供的主动埋点的方案。内部框架默认集成,开箱即用。其他框架则根据我们提供的文档自行接入。不过现在回想似乎有一点厂商绑定的意思,不过也确实是当时的最优方案。
这里有一点要值得特别注意。虽然我们最终使用了官方方案。但是并没有直接引用官方包。而是fork了一份官方包在内部自行维护,并及时同步官方最新代码。这样做的好处有如下几点:
  1. 增强官方包数据收集能力(主要原因)。官方的遥测包中收集的都是规约约定的最小集合。并不能满足后续的根因分析。(fork的代码仅做增强处理。不掺杂业务属性)
  1. 新增公司内部中间件遥测数据包的支持
  1. 控制版本。保证对业务提供的包安全可用、相对的代码审计。

OTLP (OpenTelemetry Collector)

notion image
OTLP 提供了一个与供应商无关的实现,用于接收、处理和导出遥测数据。它消除了运行、操作和维护多个代理/收集器的需要。这可以提高可伸缩性,并支持发送到一个或多个开源或商业后端的开源可观测性数据格式,例如 Jaeger、 Prometheus、 Fluent Bit 等。(官网解释)
如上图可以看到,OTLP上报有两种方案。这两种方案在图中看起来好像没什么区别,为什么还会有两个名字区分呢?接下来我们就聊聊 Agent 和 Gateway 分别是什么,有什么区别。
注:最新文档中,已将 Service 模式改名为 Gateway 。
无论是 Agent 还是 Gateway,他们都是官方的OTLP服务。只是不同的部署方式的所对应的不同叫法。当我们把OTLP与服务部署在相同主机时,此时便叫做 Agent,如果是独立的集群部署,与服务主机无关,Gateway 作为独立服务运行。除了部署方式的区别之外。个人理解他们侧重点也会有一些区别。对于Agent,更应该关注的是数据的简单关联与聚合。同时因为是本机部署。减少了应用与Agent数据上报的网络开销。同时还可以注入或修改Attributes。更灵活。当然缺点也是有的,就是单机处理的性能有限,也会增加本机的各种负担,进而影响到同宿主机的应用。所以也只能处理一些简单的数据处理。不可以过重。
相对的,Gateway 则可以弥补 Agent 的不足。可以集群化部署,提高可用性,提高数据处理的吞吐能力。可以处理更重的逻辑。比如过滤逻辑、染色逻辑、数据清洗逻辑等等。
推荐 Agent + Gateway 的模式。两者可以取长补短。虽然会有一些额外的开销,但我认为相较于收益来说,这是值得的。
notion image
遥测数据经过 Gateway 处理后 ,数据会被上报到各自的后端服务。比较常见的后端服务有Jaeger、Skywalking、Elasticsearch、Prometheus等等。也可以将这些数据导入各种流计算中,方便对数据分析存储。OTLP的数据接收服务统称后端服务。
notion image

存储及数据分析

对于这种海量的流式数据处理分析,可能我们第一时间想到的就是上大数据套件,也是很多公司的现有方案。不过从成本出发,无论是人力成本还是机器成本,我们都第一个把它排出掉了,对于当时的我们来说,过于臃肿且不可控。由于OTLP本身的架构设计里就是有数据处理模块的,且各模块之间配合默契,相互之间插拔式合作,那么完全可以用OTLP本身的功能进行数据处理。数据分析则可以完全交给ClickHouse。ClickHouse既可以做到高效存储,又可以基于本身强大的聚合函数能力进行数据分析。

OTLP

OTLP架构图
OTLP架构图
从OTLP的架构图我们可以知道。OTLP对自身各职能抽象划分的特别详细明确。各自间相互配合且不存在耦合。这样的好处是假设我想针对接收侧开发一个针对内部的特殊插件,全局其他部分并不会因此修改而受到牵连。其他部分的能力也可以完美继承。这样我们便可以针对性的开发相应模块,复用通用模块,进而大幅的节省了维护与开发成本。接下来就说一下在OTLP部分我们做了哪些事情。
notion image
  • Receiver
上文说道,由于PHP扩展内部支持了udp进行数据上报,官方并不提供对应的数据收集。所以我们开发了一个 OtlpUDPReceiver 插件用于支持udp数据接收。
  • Extension
由于现在服务已经推广至不同部门,那么成本分摊,用量统计也成为了我们要考虑的问题。所以我们开发了一个内部的权限校验的扩展。然后基于此扩展对所有Receiver接收到的数据进行身份统计校验。这样既可以动态控制不同业务方的上报速度、权限,还可以基于此统计后续的数据存储使用情况。
  • Processor
数据处理部分,我们开发了 FilterProcessor 、AttributeProcessor 两个插件。分别用于数据过滤和标签自动归一、清洗染色等逻辑处理。这也是整个数据处理中最核心、逻辑最重的两个部分。
FilterProcessor 主要用于标签过滤,span过滤等。最终目的都是进行数据采样收集。这部分可以Agent与Gateway两种部署模式共同承担。Agent侧承担简单轻量的标签过滤,如基于URL,服务名等,减少Gateway的负担。Gateway侧则进行数据逻辑比较重的操作。
AttributeProcessor 是整个数据处理模块中,最重要的部分。它负责将不同系统收集上来的数据进行标签归一化操作。比如官方约定的本机网络ip attribute key 命名为 net.host.ip 有可能有些系统上报上来的不规范叫做 host_ip ,那么我们就要讲这些可预测不规范标签进行规范化。同时,对于部分数据可以进行数据处理。比如某缓存指令为 set cache_key cache_value 。那么我们在此处可以讲此指令拆解为 操作 get 缓存key cache_key 存储数据为 cache_value 。后续便可基于此来分析缓存数据值的大小。以此预估此key值是否为大key。可以统计此key是否会造成带宽打满的问题。比如 MySQL,我们可以拆解SQL语句,分析SQL调用量,分析SQL慢查询原因等等。其他模块的数据分析处理也是类似的,这里的想象空间可以无限大。
 
  • Exporter
针对这些数据,我们还可以对其进行更深入的处理,比如分析MySQL中的慢查询,进行缓存统计,统计带宽使用等等,以达到更好的性能调优。为此,我们开发了几个OTLP插件,包括Receiver、Extension、Processor和Exporter,它们可以结合使用,以有效的分析数据,并可以将数据导出至Apm等服务中。

ClickHouse

另外,我们还采用了ClickHouse作为OTLP的数据存储介质,以确保数据的高效存储和分析。ClickHouse的存储机制采用了列式存储,可以使查询的效率提升至毫秒级,并可以做到在不影响存储效率的情况下,存储更多的历史数据以及更大量的数据量。此外,ClickHouse还支持多重查询,以及聚合函数等,满足了我们对数据分析的要求。
为了有效的分析和存储数据,我们使用了OTLP和ClickHouse,OTLP用于接收、过滤和处理数据,ClickHouse用于存储和分析数据,它的列式存储可以提升查询效率,支持多重查询和聚合函数。此外,为了更好的性能调优,我们还开发了Exporter插件,用于对数据进行更深入的分析,比如MySQL慢查询统计、缓存统计、带宽使用等。
🚧🚧🚧 施工中 🚧🚧🚧

一站式可观测平台

🚧🚧🚧 施工中 🚧🚧🚧

案例与成果

🚧🚧🚧 施工中 🚧🚧🚧

未来展望

  • 根因分析 智能告警 故障报告 (重点)
  • 日志分析与串联
  • 结合业务特性深度定制保障方案
  • 混沌工程、流量染色、ab实验
  • ……

Q&A

  • 🚧🚧🚧 施工中 🚧🚧🚧
 
本文尚未完成、还在不断完善更新。填充骨架、完善细节。🚧🚧🚧 施工中 🚧🚧🚧

附件

备注

作为 GopherChina 2022 大会分享的演讲稿。
更新:2022-11-23 08:00 GopherChina 2022 大会因为疫情原因取消了😂 。
为此准备的相关遗产附在附录里了。
更新:2023-04-06 08:00 GopherChina 2023 大会复活了。看来遗产还能用用。