目录
对微服务架构的实现或云原生架构来说,随着系统的运行,在这个过程中,一个非常重要的关注点就是应用可观测性,分布式服务的本质决定了需要对它进行有效的度量与观测。
通俗来讲,可观测性被定义为根据系统产生的输出数据,如日志,指标和链路追踪来衡量当前系统运行状态的能力。
可观测性目前被广泛的用于提升分布式 IT 系统的稳定性(系统复杂度成倍提升,在故障或者异常时很难快速定位和解决),它利用指标、日志和链路追踪三种类型数据,为分布式系统内部运行状态提供了深度透视能力,协助 DevOps 工程师解决各种问题并提升系统性能。
如下图,是应用可观测的三个维度,也称应用可观测性的三大基石
指标:Metrics
用于衡量应用程序性能和行为的定量数据,通过收集和分析指标,可以全方位的了解和掌握应用程序的运行状态,比如请求响应时间,吞吐量,错误率等,指标可以帮助发现系统的性能问题,预测系统资源需求并指导容量规划。
日志对于任何系统来说都是最基础也是最重要的存在,既是应用出现故障时排查和分析的第一资料,也是做很多统计分析的原始数据来源,日志简单来说是特定的事件在特定的时间发生的文本记录。
生成日志条目的触发器是应用程序代码的一部分,因此执行相关代码时,系统会重复的产生日志条目。日志通常记录了时间发生的时间,并提供了载荷,包括描述事件性质,事件上下文,以及后续其他可能有用的元数据。
根据日志创建方式,使用日志的格式化规则,以及自动化处理逻辑的难度,广义上日志大致可以分为下面几类:
日志提供了应用程序行为的可靠且易于理解的信息源,对于大多数编程语言来说,已经内置了日志功能,因此大多数情况下事件的日志记录很简单,在面对非典型或极端事件的场景下表现出色,日志它能够提供更详细的信息和上下文,这是通过平均值和百分位数指标无法涵盖或揭示的。
俗话说无追踪不监控,追踪通俗理解就是链路追踪,在分布式系统中,即端到端的请求流程可以构成一条完整的调用链,这个调用链就代表了一系列分散事件的具体请求路径。而链路追踪,即使用某种手段对这个链路上的各个环节进行跟踪,比如日志埋点,接入agent等,然后通过可视化的链路追踪工具进行分析。
追踪描述了请求在分布式系统中的整个路径,当前请求进入系统,处理他们的组件创建跨度(span),这些跨度记录了操作,比如即“接收请求API接口地址”,“XXX查询了数据库”,操作的开始时间点以及完成所花费的所有时间。
跨度根据它们的追踪标识进行分组,并链接到它们的前身跨度,有效创建了跨度的有向无环图,展示出分布式系统中如何进行请求处理的完整过程。根据在追踪中收集到的信息的细粒程度,通常可以一目了然的看到一个请求在处理过程中发生的错误,延迟,起源等信息,以及如何在分布式系统中进行传播的。
跨度通常包含如下数据:
追踪标识符,通常为traceId;
跨度标识符,通常用spanId标识;
操作的名称;
开始结束时间戳;
OpenTelemetry 是一个开源框架,用于创建和管理遥测数据,包括指标、日志和监控数据,太提供了工具、SDK、集成和API,使得开发人员能够得到与供应商无关的业务实现,从而将遥测数据发送到现有的监控和跟踪系统。
具体来说:
遥测数据是指为了达到可观测系统的目的而从源系统收集的任何可输出的数据,这些数据一起进行分析,以查看分布式系统内的依赖关系和关联。
目前主要有三种类型的数据被称为可观测性的三大支柱,即日志,指标和追踪,随着时间的推移,OpenTelemetry 可以扩展以收集其他类型的遥测数据,比如性能分析,和端用户监控等。
如下是一张关于OpenTelemetry 包含了核心组件的架构图,关于其中的各个组件下面做详细的介绍。
Application
一般的应用程序,同时使用了 OpenTelemetry 的 Library (实现了 API 的 SDK)。即按照特定的格式生成遥测数据,比如跟踪、指标和日志,可能涉及到使用OpenTelemetry 的SDK相关代码,并使用OpenTelemetry API来创建和导出遥测数据。
SDK
OpenTelemetry SDK(软件开发工具包)是一个库和工具的集合,使开发人员能够对其应用程序进行检测并收集遥测数据以进行监控。通常用于负责在客户端程序里采集观测数据,包括 metrics,traces,logs,对观测数据进行处理,之后观测数据按照 exporter 的不同方式,通过 OTLP 方式发送到 Collector 或者直接发送到 Backend 中。
exporter
导出器,将应用生成的遥测数据导出发送到不同的后端服务,比如skywalking的OAP,jaeger等,导出器负责将数据转换为适当的格式并发送到指定的目标服务上去。
Receiver
接收器,收集器需要使用接收器来接收来做各个应用程序的遥测数据。接收器一般允许多种协议,比如OTLP,HTTP等,方便接收数据。比如通常使用接收器接收微服务应用中的跟踪数据和指标数据,或者特定格式输出的日志数据。
Collector
收集器,在应用程序与上报的应用后端之间,存在一个或多个OpenTelemetry收集器。这些收集器接收来做应用程序中的遥测数据,然后根据配置或指定的过滤条件进行处理和筛选。它们充当了一个缓存层,以确保数据以可靠的方式发送到后端,并且不会对应用程序本身造成性能上的重大影响。
Telemetry后端
最后,收集器收集的遥测数据被上报到遥测后端,用于存储,查询和可视化展现,存储的选择可以有多种,比如mysql,es等,而展现通常借助一些可视化的工具,比如prometheus,ELK,grafana 等。通过展现的可视化指标数据一方面可以监控应用程序的整体情况,另一方面还能识别系统的性能问题。
其实在OpenTelemetry 之前,链路追踪与应用可观测概念已经被提出来了,而且行业中逐渐出现了一些解决方案,但并没有形成一套系统的标准或规范。
对于很多开发人员来说,想让应用支持分布式追踪太难了。不仅需要在进程内进行追踪数据的传递,还要在进程之间传递。更难的是,还需要其他组件对分布式跟踪的支持,比如 NGINX, Cassandra, Redis 等开源服务,或者在服务内引入的 gRPC, ORMs 等开源库。
在 OepnTracing 之前,一方面,很多分布式追踪系统通过使用不兼容 API 的应用程序级检测进行实现,这使得开发人员对应用与任何特定的分布式跟踪紧密耦合。另一方面,这些应用程序级检测 API 具有非常相似的语义。为了解决不同的分布式追踪系统 API 不兼容问题,或者说追踪数据从一个库到另一个库和一个进程到下一个进程传递过程中的标准化问题,诞生了 OpenTracing 规范。位于应用程序/类库和追踪或日志分析程序之间的轻量级标准化层。
OpenTracing 优势在于制定了一套无关厂商、无关平台的协议标准,使开发人员只需要修改 Tracer 就可以更迅捷的添加或更换底层监控的实现。也是基于这一点,2016 年云原生计算基金会 CNCF 正式接纳 OpenTracing,顺利成为 CNCF 第三个项目。而前两个项目都已成为云原生及开源领域的事实标准–Kubernetes 和 Prometheus。由此也可以看到行业对于可观测及统一标准的重视程度。
OpenTracing 由 API 规范、实现该规范的框架和库,以及项目文档组成,并进行以下努力:
在整个可观测领域,为了更好实现 DevOps,除了分布式追踪 Trace,应用系统开始关注 Log 和 Metrics。Metrics 指标监控作为可观测的重要组成部分,包括 CPU、内存、硬盘、网络等机器指标,gRPC 请求延迟、错误率等网络协议指标,用户数、访问数等业务指标。
OpenCensus 提供了统一的测量工具:跨服务捕获跟踪跨度 Span、应用级别指标 Metrics。
OpenCensus特点:
OpenCensus优势:
通常,当线上的微服务出现问题的时候,我们的排查流程是怎样的呢?看看是不是下面这样:
可以说,为了能获得更好的可观测性以及快速解决上述问题,Tracing、Metrics、Logs缺一不可。
与此同时,行业中已经有了丰富的开源及商业方案,其中包括:
Metric:Zabbix、Nagios、Prometheus、InfluxDB、OpenFalcon、OpenCensus;
Tracing:Jaeger、Zipkin、SkyWalking、OpenTracing、OpenCensus;
Logs:ELK、Splunk、SumoLogic、Loki、Loggly;
可以看到,针对不同的维度,解决方案也不同,同时各个方案也有着不同的协议格式/数据类型。更尴尬的是不同的方案之间很难兼容/互通,同时,实际业务场景中由于技术选型的不同,或者团队技术的参差不齐也会将各种方案混用,开发人员只能自己开发各类 Adapter 去兼容。
为了更好的将 Traces、Metrics 和 Logs 融合在一起,OpenTelemetry 诞生了。作为 CNCF 的孵化项目,OpenTelemetry 由 OpenTracing 和 OpenCensus 项目合并而成,是一组规范、API 接口、SDK、工具和集成。为众多开发人员带来 Metrics、Tracing、Logs 的统一标准,三者都有相同的元数据结构,可以轻松实现互相关联。
OpenTelemetry 与厂商、平台无关,不提供与可观测性相关的后端服务。可根据用户需求将可观测类数据导出到存储、查询、可视化等不同后端,如 Prometheus、Jaeger 、云厂商服务中。当前,像阿里云,腾讯云等云厂商都提供了基于OpenTelemetry的云上解决方案,方便应用快速接入。
OpenTelemetry具备如下优势:
OpenTelemetry ,OpenCensus 以及OpenTracing 都是与应用可观测性相关的项目和标准,它们之间有一定的关系和演进历史,结合上文的介绍,具体来说:
综合来说,OpenTelemetry 可以看作是OpenTracing 和OpenCensus 的下一代,它整合了这两个项目的优点,并提供了更加全面的可观测性方案,因此如果你在实际项目中考虑集成,建议选择OpenTelemetry ,因为它代表了未来的方向,并且具有更丰富的功能和更广泛的支持。
OpenTelemetry 在实际的架构选择中有很多种组合和实现方案,接下来分别来了解一下 OpenTelemetry 的常用实现方案。
OpenTelemetry 作为经典的对各各类遥测数据处理架构,使用开源工具可将不同类型的数据存储在不同的平台,比如日志存放在 ELK,追踪存放在 Jaeger 这类 云原生友好的APM 工具,而指标保存在 Prometheus 并通过 Grafana 进行视图展示。组件的整体配置如下图所示:
以Java技术栈中使用springboot构建的微服务应用来说,按照上述的流程,其完整的数据采集和传输过程如下:
从上图不难发现,需求的不同或者说实际在技术选型时的复杂性要求不同,有的只需要展示日志,有的同时需要展示指标,日志以及链路监控数据,其方案选择也略有不同,比如在上图中针对日志收集就有两种不同的方式:
随着近些年可观测性的流行,Prometheus得到广泛的应用,同时Grafana也开始出现在人们的视野中,Prometheus与Grafana的结合,让可观测性的展现更加全面也更加友好,使用 Grafana 对接 OpenTelemetry 的架构如下图所示,这里面主要用到 Grafana Tempo 和 Loki 两个组件:
对于流程中的各个组件做如下介绍:
整个执行流程如下:
“ Grafana Tempo + Loki” 这个组合能够让我们直观地看到日志链路情况,但 Loki 的特性也决定了它并不能高效分析和处理大型生产系统的日志。日志链路只是可观测的一部分,仅仅通过日志链路查询并不能解决大部分问题,特别是在微服务云原生架构时代,多种多样的问题需要我们结合各方面进行分析。
随着云服务商提供的云上服务能力增强,像阿里云,腾讯云等服务商也开始逐步涉入OpenTelemetry ,如下是两大云厂商的接入点:
腾讯云接入点:手动埋点上报-应用性能监控-文档中心-腾讯云
阿里云接入点:如何快速接入可观测链路 OpenTelemetry 版 - 可观测链路 OpenTelemetry 版 - 阿里云
观测云特点:
观测云能够采集指标、链路、日志以及所有的可观测数据,并将它们进行关联和整合分析,实现系统完整的可观测性;
关于DataKit 做如下补充说明:
由于 DataKit 是接收 OTLP 协议的,所以我们可以把 OpenTelemetry Collector 的 Exporter 设置为 OTLP(指向 DataKit),也可以直接将数据打给 DataKit。因此这里有两种方案。
方案一:
方案二:
当众多的云厂商也介入应用可观测性领域,微服务与OpenTelemetry 的整合集成就变得更容易了,对客户端来说,甚至不需要独立部署用于链路展示的服务平台,而是直接将遥测数据上报到云平台即可,由云平台提供大屏展示的链路数据,指标数据等。
aeger是一款广受欢迎的开源分布式链路跟踪系统,受到Zipkin的启发由 Uber 创建的分布式追踪平台,用于监控和诊断分布式应用程序和微服务架构中的性能问题。官网地址:jaeger官网
它兼容OpenTracing API,且已加入CNCF开源组织。其主要功能是聚合来自各个异构系统的实时监控数据。它用于监控和故障排查基于微服务的分布式系统,其核心功能点如下:
下面是官方给出的架构图
对于这张图中,几个核心的组件做如下说明:
可扩展性好
Jaeger后端为无单点故障设计,可随时根据需要进行扩展ub,er每天使用它处理几十亿级别的span
原生支持OpenTracing
Jaeger后端、webUI、以及相关的框架适配库的设计实现都是支持OpenTracing标准的;
支持云原生部署
- 官方已将Jaeger后端打包为docker镜像发布;
- 二进制文件支持CLI选项、ENV、配置文件方式三种方式加载配置;
- K8s部署, 参考Kubernetes operator,?Kubernetes templates?and a?Helm chart
支持可观测性组件集成
Jaeger后端组件均支持暴露指标到Prometheus(其他监控后端也支持);
Log是通过第三日志库zap写到stdout;
向后兼容Zipkin client
如果你已经使用Zipkin作为trace平台,并且希望迁移到Jaeger,不用太担心;
无需重写client代码,Jaeger后端支持Zipkin格式的span,只需要将数据的转发目的地指向Jaeger后端就行。
Jaeger 在架构的设计上沿用了 Zipkin 的架构风格,两者具备很多类似的特性,除了开发语言不同而已。作为后起之秀,基于 Go 的强大特性,使得 Jaeger 在基于云原生生态领域中能够如鱼得水,具备强大的号召力,甚至在一些新技术框架领域中,作为默认首选的分布式链路追踪系统,落地于各种不同的业务场景。虽然已在 2012 年启动研发,但相对于 2017 年启动的 Jaeger 而言,Zipkin 与 Jaeger 在社区中发展势态几乎没多大差异,从侧面说明,Jaeger 已成为新一代的云原生链路追踪系统的布道者。其支持跨平台、多样性的组件追踪,例如:分布式边缘路由组件 Traefik、下一代微服务体系 Istio 等等。
下列表简要对比了下当前在各大企业中,所采用链路追踪系统的特性对比情况,具体来说:
后面我们会通过微服务集成OpenTelemetry,然后将链路追踪信息上报jaeger并通过jaeger进行展示,下面通过docker搭建jaeger服务。
docker pull jaegertracing/all-in-one:latest
使用下面的命令启动一个jaeger容器
docker run -d --name jaeger \
-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
-p 5775:5775/udp \
-p 6831:6831/udp \
-p 6832:6832/udp \
-p 5778:5778 \
-p 16686:0.0.0.0/0 \
-p 14250:14250 \
-p 14268:14268 \
-p 14269:14269 \
-p 9411:9411 \
jaegertracing/all-in-one:latest
访问地址:http://IP:16686/search,看到如下界面;
使用过skywalking的同学应该不陌生,在springboot中要想通过skywalking监控服务链路并展示链路信息,只需要启动时利用skywalking提供的Agent,然后指定skywalking服务端端点即可。
同样,如果需要将springboot服务的链路追踪信息上报jaeger,也需要一个Agent,或者手动埋点,或者集成sdk的方式结合编码进行,这里提供一种最简单的操作方案,即使用OpenTelemetry提供的Agent方式进行集成。下载Agent,opentelemetry-javaagent.jar,下载地址:agent下载地址
选择具体的版本之后,下载第一个agent的包
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
@Autowired
private UserService userService;
//http://localhost:8088/user/get?userId=001
@GetMapping("/get")
public Object getUserInfo(String userId){
Map userInfo = userService.getUserInfo(userId);
return userInfo;
}
}
启动服务时使用下面的参数
-javaagent:E:\code-self\opentelemetry-javaagent.jar -Dotel.service.name=your-service-name -Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaeger IP:14250
该参数的含义解释:
启动完成后,尝试调用一下接口
接口调用成功后,进入到jaeger的UI界面,可以通过trace查看调用的详细信息?
也可以使用相同的方式在springcloud中通过Agent上报链路追踪等指标信息到jaeger,以之前的一个工程案例进行说明,在user,order,gateway三个模块中,启动的时候分别使用参数的方式启动
-javaagent:E:\code-self\opentelemetry-javaagent.jar -Dotel.service.name=user-service -Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://IP:14250
-javaagent:E:\code-self\opentelemetry-javaagent.jar -Dotel.service.name=order-service -Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://IP:14250
-javaagent:E:\code-self\opentelemetry-javaagent.jar -Dotel.service.name=gate-service -Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://IP:14250
服务启动后,通过走网关调用一下接口
然后通过UI界面检查jaeger的服务监控信息,服务是从order发起的,我们检查下上面的接口
点击进去之后可以查看接口调用的详情
也可以在拓扑图中进行视察,服务的调用过程更形象
小结:
事实上,利用jaeger的能力,结合上述的Agent,还可以接入像Prometheus这样的指标可视化的监控组件,从而更详细的了解应用系统的各种指标监控信息。
本文通过较大的篇幅详细介绍了应用可观测性的理论,以及OpenTelemetry在应用客观性中的使用,最后通过微服务使用OpenTelemetry提供的Agent上报链路追踪信息到jaeger,事实上,OpenTelemetry可以理解为一种标准化的解决思想,在实际项目或技术选型中,可以有多种解决方案,可以结合自身的情况选择一种适合当前业务现状的即可。本篇到此结束感谢观看。