作者:David Hope
在快节奏的软件开发领域,特别是在云原生领域,DevOps 和 SRE 团队日益成为应用程序稳定性和增长的重要合作伙伴。
DevOps 工程师不断优化软件交付,而 SRE 团队则充当应用程序可靠性、可扩展性和顶级性能的管理者。 挑战? 这些团队需要一种尖端的可观察性解决方案,该解决方案包含全栈洞察,使他们能够在潜在的干扰最终导致运营挑战之前快速管理、监控和纠正它们。
现代分布式软件生态系统中的可观察性不仅仅是监控 —— 它需要无限的数据收集、处理精度以及将这些数据与可操作的见解相关联。 然而,实现这一整体视图的道路充满了障碍,从解决版本不兼容性到与限制性专有代码作斗争。
OpenTelemetry (OTel) 将为采用它的用户带来以下好处:
- 通过 OTel 摆脱供应商限制,将自己从供应商锁定中解放出来,并确保一流的可观察性。
- 查看统一日志、指标和跟踪的和谐统一,以提供完整的系统视图。
- 通过更丰富和增强的工具来改善您的应用程序监督。
- 利用向后兼容性的优势来保护你之前的检测投资。
- 通过简单的学习曲线踏上 OpenTelemetry 之旅,简化入门和可扩展性。
- 依靠经过验证的、面向未来的标准来增强你对每项投资的信心。
在本博客中,我们将探讨如何使用 Docker 在 Java 应用程序中使用自动检测,而无需重构应用程序代码的任何部分。 我们将使用一个名为 Elastiflix 的应用程序,它有助于以简单的方式突出显示自动检测。
应用程序、先决条件和配置
我们在这个博客中使用的应用程序称为 Elastiflix,一个电影流应用程序。 它由多个用 .NET、NodeJS、Go 和 Python 编写的微服务组成。
在我们检测示例应用程序之前,我们首先需要了解 Elastic 如何接收遥测数据。
Elastic Observability 的所有 APM 功能均可通过 OTel 数据使用。 其中一些包括:
- 服务地图
- 服务详细信息(延迟、吞吐量、失败的 transactions)
- 服务之间的依赖关系、分布式追踪
- Transactions(跟踪)
- 机器学习 (ML) 相关性
- 日志相关性
除了 Elastic 的 APM 和遥测数据的统一视图之外,你还可以使用 Elastic 强大的机器学习功能来减少分析,并发出警报以帮助降低 MTTR。
先决条件
- Elastic Cloud 帐户 — 立即注册。
- 克隆 Elastiflix 演示应用程序,或你自己的 Java 应用程序
- 对 Docker 的基本了解 — 可能安装 Docker Desktop
- 对 Java 有基本的了解
查看示例源代码
完整的源代码,包括本博客中使用的 Dockerfile,可以在 GitHub 上找到。 该存储库还包含相同的应用程序,但没有检测。 这使你可以比较每个文件并查看差异。
以下步骤将向您展示如何实现此应用程序并在命令行或 Docker 中运行它。 如果您对更完整的 OTel 示例感兴趣,请查看此处的 docker-compose 文件,它将显示完整的项目。
分步指南
步骤 0:登录您的 Elastic Cloud 帐户
本博客假设你有 Elastic Cloud 帐户 - 如果没有,请按照说明开始使用 Elastic Cloud。
步骤 1:为 Java 服务配置自动检测
我们将通过 Elastiflix 演示应用程序中的 Java 服务使用自动检测。
我们将使用 Elastiflix 的以下服务:
Elastiflix/java-favorite-otel-auto
根据 OpenTelemetry Automatic Instrumentation for Java 文档和文档,你只需安装适当的 Java 包即可。
创建本地 OTel 目录以下载 OpenTelemetry Java 代理。 下载 opentelemetry-javaagent.jar。
>mkdir /otel
>curl -L https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar –output /otel/opentelemetry-javaagent.jar
如果要在命令行上运行该服务,则可以使用以下命令:
java -javaagent:/otel/opentelemetry-javaagent.jar \
-jar /usr/src/app/target/favorite-0.0.1-SNAPSHOT.jar --server.port=5000
对于我们的应用程序,我们将把它作为 Dockerfile 的一部分来执行。
Dockerfile
Start with a base image containing Java runtime
FROM maven:3.8.2-openjdk-17-slim as build
# Make port 8080 available to the world outside this container
EXPOSE 5000
# Change to the app directory
WORKDIR /usr/src/app
# Copy the local code to the container
COPY . .
# Build the application
RUN mvn clean install
USER root
RUN apt-get update && apt-get install -y zip curl
RUN mkdir /otel
RUN curl -L -o /otel/opentelemetry-javaagent.jar https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v1.28.0/opentelemetry-javaagent.jar
COPY start.sh /start.sh
RUN chmod +x /start.sh
ENTRYPOINT ["/start.sh"]
步骤 2:使用环境变量运行 Docker 镜像
按照 OTEL Java 文档中的规定,我们将使用环境变量并传入配置值以使其能够与 Elastic Observability 的 APM 服务器连接。
由于 Elastic 本身接受 OTLP,因此我们只需要提供 OTEL Exporter 需要发送数据的端点和身份验证,以及一些其他环境变量。
获取 Elastic Cloud 变量
你可以从 Kibana 的路径 “/app/home#/tutorial/apm” 下复制端点和令牌。
你将需要复制以下环境变量:
OTEL_EXPORTER_OTLP_ENDPOINT
OTEL_EXPORTER_OTLP_HEADERS
构建 Docker 镜像
docker build -t java-otel-auto-image .
运行 Docker 镜像
docker run \
-e OTEL_EXPORTER_OTLP_ENDPOINT="REPLACE WITH OTEL_EXPORTER_OTLP_ENDPOINT" \
-e OTEL_EXPORTER_OTLP_HEADERS="REPLACE WITH OTEL_EXPORTER_OTLP_HEADERS" \
-e OTEL_RESOURCE_ATTRIBUTES="service.version=1.0,deployment.environment=production" \
-e OTEL_SERVICE_NAME="java-favorite-otel-auto" \
-p 5000:5000 \
java-otel-auto-image
你现在可以发出一些请求来生成跟踪数据。 请注意,这些请求预计会返回错误,因为此服务依赖于你当前未运行的 Redis 连接。 如前所述,你可以在此处找到使用 docker-compose 的更完整示例。
curl localhost:5000/favorites
# or alternatively issue a request every second
while true; do curl "localhost:5000/favorites"; sleep 1; done;
步骤 3:探索 Elastic APM 中的跟踪和日志
启动并运行此程序后,你可以 ping 检测服务的端点(在我们的示例中为 /favorites),你应该会看到该应用程序出现在 Elastic APM 中,如下所示:
它将首先跟踪 SRE 需要关注的吞吐量和延迟关键指标。
深入研究,我们可以看到所有 transactions 的概述。
再看看具体的 transactions:
点击 Logs,我们看到日志也带了过来。 OTel Agent 将自动引入日志并将其与你的跟踪关联起来:
这使你可以完全了解日志、指标和跟踪!
基本概念:APM 如何与 Java 配合使用
在继续之前,我们首先了解一些基本概念和术语。
- Java Agent:这是一个可用于检测(或修改)Java 虚拟机 (JVM) 中类文件字节码的工具。 Java 代理有多种用途,例如性能监控、日志记录、安全性等。
- Bytecode:这是 Java 编译器根据 Java 源代码生成的中间代码。 该代码由 JVM 即时解释或编译,以生成可以执行的机器代码。
- Byte Buddy:Byte Buddy 是一个 Java 代码生成和操作库。 它用于在运行时创建、修改或调整 Java 类。 在 Java Agent 的上下文中,Byte Buddy 提供了一种强大且灵活的方式来修改字节码。 Elastic APM 代理和 OpenTelemetry 代理都在幕后使用 Byte Buddy。
现在,我们来谈谈自动检测如何与 Byte Buddy 配合使用:
自动检测是代理修改应用程序类的字节码的过程,通常是为了插入监视代码。 代理并不直接修改源代码,而是修改加载到 JVM 中的字节码。 这是在 JVM 加载类时完成的,因此修改在运行时有效。
以下是该过程的简化说明:
- 使用代理启动 JVM:启动 Java 应用程序时,可以使用 -javaagent 命令行选项指定 Java 代理。 这会指示 JVM 在调用应用程序的 main 方法之前加载代理。 此时,代理有机会设置类转换器(class transformers)。
- 向 Byte Buddy 注册类文件转换器:你的代理将向 Byte Buddy 注册类文件转换器。 转换器是每次将类加载到 JVM 时都会调用的一段代码。 该转换器接收类的 bytecode,并且可以在实际使用该类之前修改该字节码。
- 转换字节码:当调用转换器时,它将使用 Byte Buddy 的 API 来修改字节码。 Byte Buddy 允许你以高级、富有表现力的方式指定转换,而不是手动编写复杂的字节码。 例如,你可以指定要检测的某个类和该类中的方法,并提供一个 “拦截器” 来向该方法添加新行为。
- 例如,假设你想要测量方法的执行时间。 你将指示 Byte Buddy 定位特定的类和方法,然后提供一个拦截器,用计时代码包装方法调用。 每次调用此方法时,都会首先调用拦截器并测量开始时间,然后调用原始方法,最后测量结束时间并打印持续时间。
- 使用转换后的类:一旦代理设置了其转换器,JVM 就会像往常一样继续加载类。 每次加载类时,都会调用转换器,允许它们修改字节码。 然后,你的应用程序将使用这些转换后的类,就像它们是原始类一样,但它们现在具有你通过拦截器注入的额外行为。
本质上,Byte Buddy 的自动检测就是在运行时修改 Java 类的行为,而不需要直接更改源代码。 这对于日志记录、监视或安全性等横切关注点特别有用,因为它允许你将此代码集中在 Java 代理中,而不是将其分散在整个应用程序中。
总结
借助此 Dockerfile,你已将简单的 Java 应用程序转换为使用 OpenTelemetry 自动检测的应用程序。 这将极大地帮助了解应用程序性能、跟踪错误以及深入了解用户如何与软件交互。
请记住,可观察性是现代应用程序开发的一个重要方面,尤其是在分布式系统中。 借助 OpenTelemetry 等工具,理解复杂系统变得更加容易。
在这篇博客中,我们讨论了以下内容:
- 如何使用 OpenTelemetry 自动检测 Java。
- 使用 Docker 文件中的标准命令,可以高效地完成自动检测,并且无需在多个位置添加代码,从而实现可管理性。
- 使用 OpenTelemetry 及其对多种语言的支持,DevOps 和 SRE 团队可以自动检测其应用程序,轻松立即了解整个应用程序堆栈的运行状况,并缩短平均解决时间 (MTTR)。
由于 Elastic 可以支持多种摄取数据的方法,无论是使用开源 OpenTelemetry 的自动检测还是使用其本机 APM 代理进行手动检测,你都可以先关注一些应用程序,然后使用稍后以最适合你的业务需求的方式在你的应用程序中打开 OpenTelemetry。
原文:Auto-instrumentation of Java applications with OpenTelemetry | Elastic Blog