OpenTelemetry、Spring Cloud Sleuth、Kafka、Jager实现分布式跟踪
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenTelemetry、Spring Cloud Sleuth、Kafka、Jager实现分布式跟踪相关的知识,希望对你有一定的参考价值。
参考技术A分布式跟踪可让您深入了解特定服务在分布式软件系统中作为整体的一部分是如何执行的。它跟踪和记录从起点到目的地的请求以及它们经过的系统。
在本文中,我们将使用 OpenTelemetry、Spring Cloud Sleuth、Kafka 和 Jaeger 在三个 Spring Boot 微服务 中实现分布式跟踪。
我们先来看看分布式追踪中的一些基本术语。
跨度:表示系统内的单个工作单元。跨度可以相互嵌套以模拟工作的分解。例如,一个跨度可能正在调用一个 REST 端点,然后另一个子跨度可能是该端点调用另一个,等等在不同的服务中。
Trace:所有共享相同根跨度的跨度集合,或者更简单地说,将所有跨度创建为原始请求的直接结果。跨度的层次结构(每个跨度在根跨度旁边都有自己的父跨度)可用于形成有向无环图,显示请求在通过各种组件时的路径。
OpenTelemetry ,也简称为 OTel,是一个供应商中立的开源 Observability 框架,用于检测、生成、收集和导出遥测数据,例如 跟踪 、 指标 和 日志 。作为 云原生 计算基金会 (CNCF) 的孵化项目,OTel 旨在提供与供应商无关的统一库和 API 集——主要用于收集数据并将其传输到某处。OTel 正在成为生成和管理遥测数据的世界标准,并被广泛采用。
Sleuth 是一个由 Spring Cloud 团队管理和维护的项目,旨在将分布式跟踪功能集成到 Spring Boot 应用程序中。它作为一个典型Spring Starter的 . 以下是一些开箱即用的 Sleuth 工具:
Sleuth 添加了一个拦截器,以确保在请求中传递所有跟踪信息。每次调用时,都会创建一个新的 Span。它在收到响应后关闭。
Sleuth 能够跟踪您的请求和消息,以便您可以将该通信与相应的日志条目相关联。您还可以将跟踪信息导出到外部系统以可视化延迟。
Jaeger 最初由 Uber 的团队构建,然后于 2015 年开源。它于 2017 年被接受为云原生孵化项目,并于 2019 年毕业。作为 CNCF 的一部分,Jaeger 是云原生 架构 中公认的项目。它的源代码主要是用 Go 编写的。Jaeger 的架构包括:
与 Jaeger 类似,Zipkin 在其架构中也提供了相同的组件集。尽管 Zipkin 是一个较老的项目,但 Jaeger 具有更现代和可扩展的设计。对于此示例,我们选择 Jaeger 作为后端。
让我们设计三个 Spring Boot 微服务:
这三个微服务旨在:
这是为了观察 OpenTelemetry 如何结合 Spring Cloud Sleuth 处理代码的自动检测以及生成和传输跟踪数据。上面的虚线捕获了微服务导出的跟踪数据的路径,通过OTLP(OpenTelemetry Protocol)传输到OpenTelemetry Collector,收集器依次处理并将跟踪数据导出到后端Jaeger进行存储和查询。
使用 monorepo,我们的项目结构如下:
第 1 步:添加 POM 依赖项
这是使用 OTel 和 Spring Cloud Sleuth 实现分布式跟踪的关键。我们的目标是不必手动检测我们的代码,因此我们依靠这些依赖项来完成它们设计的工作——自动检测我们的代码,除了跟踪实现、将遥测数据导出到 OTel 收集器等。
第 2 步:OpenTelemetry 配置
OpenTelemetry 收集器端点
对于每个微服务,我们需要在其中添加以下配置application.yml(请参阅下面部分中的示例片段)。spring.sleuth.otel.exporter.otlp.endpoint主要是配置OTel Collector端点。它告诉导出器,在我们的例子中是 Sleuth,通过 OTLP 将跟踪数据发送到指定的收集器端点http://otel-collector:4317。注意otel-collector端点 URL 来自otel-collector图像的 docker-compose 服务。
跟踪数据概率抽样
spring.sleuth.otel.config.trace-id-ratio-based属性定义了跟踪数据的采样概率。它根据提供给采样器的分数对一部分迹线进行采样。概率抽样允许 OpenTelemetry 跟踪用户通过使用随机抽样技术降低跨度收集成本。如果该比率小于 1.0,则某些迹线将不会被导出。对于此示例,我们将采样配置为 1.0、100%。
有关其他 OTel Spring Cloud Sleuth 属性,请参阅常见应用程序属性。
OpenTelemetry 配置文件
我们需要项目根目录下的 OTel 配置文件otel-config.yaml。内容如下。此配置文件定义了 OTel 接收器、处理器和导出器的行为。正如我们所看到的,我们定义了我们的接收器来监听 gRPC 和 HTTP,处理器使用批处理和导出器作为 jaeger 和日志记录。
第 3 步:docker-compose 将所有内容串在一起
让我们看看我们需要启动哪些 docker 容器来运行这三个微服务并观察它们的分布式跟踪,前三个微服务在上面的部分中进行了解释。
运行docker-compose up -d以调出所有九个容器:
第 4 步:追踪数据在行动
快乐之路
现在,让我们启动customer-service-bff流程的入口点,以创建新客户。
启动 Jaeger UI, http://localhost:16686/ [url=https://link.zhihu.com/?target=http%3A//localhost%3A16686/%2C]按[/url]服务搜索customer-service-bff,单击Find Traces按钮,这是我们看到的创建客户跟踪:它跨越三个服务,总共跨越六个,持续时间 82.35 毫秒。
除了 Trace Timeline 视图(上面的屏幕截图),Jaeger 还提供了一个图形视图(Trace Graph在右上角的下拉菜单中选择):
三个微服务在 docker 中的日志输出显示相同的跟踪 id,以红色突出显示,并根据其应用程序名称显示不同的跨度 id(应用程序名称及其对应的跨度 id 以匹配的颜色突出显示)。在 的情况下customer-service,相同的 span id 从 REST API 请求传递到 Kafka 发布者请求。
customer-service让我们在 docker 中暂停我们的PostgreSQL 数据库,然后重复从customer-service-bff. 500 internal server error正如预期的那样,我们得到了。检查 Jaeger,我们看到以下跟踪,异常堆栈跟踪抱怨SocketTimeoutException,再次如预期的那样。
识别长期运行的跨度
Jaeger UI 允许我们搜索超过指定最大持续时间的跟踪。例如,我们可以搜索所有耗时超过 1000 毫秒的跟踪。然后,我们可以深入研究长期运行的跟踪以调查其根本原因。
在这个故事中,我们从 OpenTelemetry、Spring Cloud Sleuth 和 Jaeger 的角度解压了分布式跟踪,验证了 REST API 调用和 Kafka pub/sub 中分布式跟踪的自动检测。我希望这个故事能让你更好地理解这些跟踪框架和工具,尤其是 OpenTelemetry,以及它如何从根本上改变我们在 分布式系统 中进行可观察性的方式。
Observability:OpenTelemetry 在 Elastic APM 中的集成
OpenTelemetry 是一组 API、SDK、工具和集成,支持从你的服务中捕获和管理遥测数据,以提高可观察性。 有关 OpenTelemetry 项目的更多信息,请参阅规范。
Elastic OpenTelemetry 集成允许你重用现有的 OpenTelemetry 工具来快速分析分布式跟踪和指标,以帮助你使用 Elastic Stack 监控业务 KPI 和技术组件。
在我们之前的文章 “Observability:如何为 Java 应用进行 APM” 里,我们介绍了如何使用 Elastic 自己的方案对 Java 应用进行性能分析。在今天的教程中,我们将使用同样的例子使用 OpenTelemetry 来对 Java 应用进行 APM。相比较之前的方法,使用 OpenTelemetry 可以使得我们使用开发的标准对应用进行监控。它特别适合于一些应用既可以使用 Elastic 所提供的方案,也可以使用其它方案对应用进行监控。
在今天的练习中,我将使用 Elastic Stack 7.15.1 来进行练习。
APM Server 原生支持 OpenTelemetry 协议
重要:Elastic 的 OpenTelemetry Collector 导出器在 7.13 中被弃用,取而代之的是 Elastic Observability (OTLP) 中对 OpenTelemetry Line Protocol 的原生支持。 要了解详情,请参阅迁移。
Elastic APM Server 本身支持 OpenTelemetry 协议。 这意味着从你的应用程序和基础设施收集的跟踪数据和指标可以使用 OpenTelemetry 协议直接发送到 Elastic APM 服务器。
插桩应用(intrument applications)
要将跟踪和指标导出到 APM 服务器,请确保你已使用 OpenTelemetry API、SDK 或两者对您的服务和应用程序进行了检测。 例如,如果您是 Java 开发人员,则需要使用 OpenTelemetry 代理为 Java 检测您的 Java 应用程序。
通过定义以下环境变量,你可以配置 OTLP 端点,以便 OpenTelemetry 代理与 APM 服务器通信。
export OTEL_RESOURCE_ATTRIBUTES=service.name=checkoutService,service.version=1.1,deployment.environment=production
export OTEL_EXPORTER_OTLP_ENDPOINT=https://apm_server_url:8200
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer an_apm_secret_token"
java -javaagent:/path/to/opentelemetry-javaagent-all.jar \\
-classpath lib/*:classes/ \\
com.mycompany.checkout.CheckoutServiceServer
OTEL_RESOURCE_ATTRIBUTES | 用于标识你的应用程序的服务名称。 |
OTEL_EXPORTER_OTLP_ENDPOINT | APM 服务器 URL。 APM 服务器侦听事件的主机和端口。 |
OTEL_EXPORTER_OTLP_HEADERS | 包含 Elastic APM Secret 令牌或 API 密钥的授权标头:“Authorization=Bearer an_apm_secret_token” 或 “Authorization=ApiKey an_api_key”。 有关如何格式化 API 密钥的信息,请参阅我们的 API 密钥文档。 请注意 Bearer 和 an_apm_secret_token 之间以及 APIKey 和 an_api_key 之间所需的空格。 |
OTEL_EXPORTER_OTLP_CERTIFICATE | gRPC 客户端的 TLS 凭据证书。 (可选的) |
你现在可以在 Kibana 中验证指标和可视化指标之前收集跟踪和指标。
动手实践
我们参照之前的文章 “Observability:如何为 Java 应用进行 APM” 启动 Elastic Stack。这其中包括 Elasticsearch,Kibana 及 APM Server。请注意:我们可以在 .env 来选择 Elastic Stack 的版本。我们选择一个在 7.13 以后的版本。我们将使用相同的例子来进行演练。
首先,我们使用如下的命令来启动 Elastic Stack:
docker-compose up
按照上面的要求,我们下载 https://github.com/open-telemetry/opentelemetry-java-instrumentation OpenTelemetry Java 代理。最新的代理位于地址。我们下载这个文件并置于 Java 应用的根目录中。
$ pwd
/Users/liuxg/java/opbeans-java/opbeans
$ ls
mvnw run.sh
mvnw.cmd src
opentelemetry-javaagent.jar target
pom.xml
在 Java 应用的根目录中,我们使用如下的命令来编译:
mvn package
在编译该应用时,请选择 Java 8 来进行编译。
我们接下来创建一个叫做 run.sh 的脚本:
run.sh
export OTEL_RESOURCE_ATTRIBUTES=service.name=opbeans-java,service.version=1.0,deployment.environment=production
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:8200
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer an_apm_secret_token"
java -javaagent:./opentelemetry-javaagent.jar \\
-jar ./target/opbeans-0.0.1-SNAPSHOT.jar
因为我们的 APM 没有配置 secret token,所以针对上面的 OTEL_EXPORTER_OTLP_HEADERS 项的配置,我们可以不做任何的设置。请注意在上面我们定义的 opbeans-java 服务名称。我们使用如下的命令来让 run.sh 变为可执行:
chmod a+x run.sh
$ pwd
/Users/liuxg/java/opbeans-java/opbeans
$ ls
mvnw run.sh
mvnw.cmd src
opentelemetry-javaagent.jar target
pom.xml
我们使用如下的命令来进行运行:
./run.sh
我们可以在浏览器中打开地址:
从上面,我们可以看出来 Java 应用已经成功地运行起来了。我们可以在界面上做任意一些操作。
我们接着打开 Kibana 中的 APM 应用:
在上面,我们可以看到 opbeans-java 服务。这个也是在我们上面的 run.sh 中定义的。点击 opbeans-java 链接:
我们可以看到在 Transaction 下列出的不同的 transactions。其中对我们影响最大的一个就是排在第一位置的 /api/orders。点击该链接:
从上面的图中,我们可以看出来和在我之前文章 “Observability:如何为 Java 应用进行 APM” 中介绍的几乎一模一样的效果。我们接下来可以采取和之前文章介绍的一模一样的方式对 Java 应用进行性能分析。在这里,我就不再累述了。
参考:
【1】OpenTelemetry integration | APM Overview [7.15] | Elastic
以上是关于OpenTelemetry、Spring Cloud Sleuth、Kafka、Jager实现分布式跟踪的主要内容,如果未能解决你的问题,请参考以下文章