在快节奏的软件开发领域,尤其是在云原生领域,DevOps 和 SRE 团队正日益成为应用程序稳定性和增长的重要合作伙伴。
DevOps 工程师不断优化软件交付,而 SRE 团队则充当应用程序可靠性、可扩展性和顶级性能的管理者。挑战是什么?这些团队需要一个尖端的可观测性解决方案,该解决方案涵盖全栈洞察,使他们能够在潜在的中断升级为运营挑战之前快速管理、监控和纠正它们。
在现代分布式软件生态系统中,可观测性不仅仅是监控,它还需要无限的数据收集、精确的处理以及将这些数据关联成可操作的见解。然而,实现这种整体视图的道路充满了障碍,从应对版本不兼容到与限制性专有代码作斗争。
使用 OpenTelemetry (OTel),采用它的人员可获得以下好处:
- 通过 OTel 摆脱供应商的限制,让您摆脱供应商锁定,并确保一流的可观测性。
- 查看统一的日志、指标和跟踪的协调统一,从而提供完整的系统视图。
- 通过更丰富和增强的检测来改进您的应用程序监督。
- 利用向后兼容性的优势来保护您之前的检测投资。
- 通过简单的学习曲线开始 OpenTelemetry 之旅,从而简化入门和可扩展性。
- 依靠经过验证的、面向未来的标准来增强您对每一项投资的信心。
- 探索手动检测,以便自定义数据收集,以满足您的独特需求。
- 使用标准化的可观测性数据框架,确保跨层监控的一致性。
- 将开发与运营分离,从而最大限度地提高两者的效率。
鉴于这种情况,OpenTelemetry 作为云原生软件的无与伦比的可观测性解决方案脱颖而出,无缝地实现跟踪、监控和调试。它的优势之一是能够自动检测应用程序,让开发人员可以轻松收集宝贵的遥测数据,而无需深入研究代码修改。
在本文中,我们将深入探讨使用 Docker 检测 .NET 应用程序的方法,从而将两者的优点结合在一起:强大的可观测性,而无需代码麻烦。
涵盖内容?
- APM 如何使用 CLR 分析器功能与 .NET 配合使用
- 为 .NET 应用程序创建带有内置 OpenTelemetry 检测的 Docker 映像
- 安装并运行 OpenTelemetry .NET 分析器以进行自动检测
APM 如何使用 CLR 分析器功能与 .NET 配合使用
在我们深入了解细节之前,让我们先消除围绕 .NET 分析器和 CPU 分析器(如 Elastic® 的通用分析工具)的一些困惑 — 我们不想将这两者混淆,因为它们的目的非常不同。
在讨论分析工具时,尤其是在 .NET 的上下文中,在“.NET 分析器”和“CPU 分析器”之间遇到混淆是很常见的。虽然两者都用于诊断和优化应用程序,但它们的主要用途不同,并且在不同的级别上运行。让我们明确区分一下
.NET 分析器
-
范围:专门针对 .NET 应用程序。它旨在与 .NET 运行时(即公共语言运行时 (CLR))配合使用。
-
功能
-
用例
CPU 分析器
-
范围:比 .NET 分析器更通用。它可以分析任何应用程序,无论其语言或运行时如何,只要它在被分析的 CPU 上运行。
-
功能
-
用例
虽然 .NET 分析器和 CPU 分析器都有助于优化和诊断应用程序性能,但它们的方法和深度有所不同。.NET 分析器专门提供对 .NET 生态系统的深入了解,从而可以进行细粒度的分析和检测。相比之下,CPU 分析器提供更广泛的视图,专注于任何应用程序的 CPU 使用模式,而与其开发平台无关。
值得注意的是,要对 .NET 应用程序进行全面分析,您可能需要同时使用两者:.NET 分析器用于了解特定于 .NET 的代码级行为,而 CPU 分析器用于概述 CPU 资源利用率。
现在我们已经澄清了这一点,让我们专注于 .NET 分析器,我们将在本文中讨论它,用于自动检测 .NET 应用程序。首先,让我们熟悉一些与 .NET 分析器相关的基本概念和术语
- CLR(公共语言运行时):CLR 是 .NET 框架的核心组件,充当 .NET 应用程序的执行引擎。它提供内存管理、异常处理和类型安全等关键服务。
- 分析器 API:.NET 提供了一组用于分析应用程序的 API。这些 API 使工具和开发人员能够在运行时监控或操作 .NET 应用程序。
- IL(中间语言):编译后,.NET 源代码转换为 IL,这是一种低级的、平台无关的表示形式。然后,此 IL 代码由 CLR 在应用程序执行期间即时 (JIT) 编译为机器代码。
- JIT 编译:JIT 代表即时。在 .NET 中,CLR 在执行之前将 IL 编译为本机代码。
现在,让我们探索如何使用 CLR 分析器进行自动检测。
.NET 中的自动检测(与 Java 的字节码检测非常相似)围绕在运行时修改应用程序方法的行为,而无需更改实际的源代码。
以下是逐步分解
-
附加分析器:启动 .NET 应用程序时,您必须指定加载分析器。CLR 通过读取环境变量来检查是否存在分析器。如果找到,CLR 将在执行任何用户代码之前初始化分析器。
-
使用 Profiler API 监控事件: Profiler API 允许性能分析器监控各种事件。例如,可以跟踪方法 JIT 编译事件。当一个方法即将进行 JIT 编译时,性能分析器会收到通知。
-
操作 IL 代码: 在收到 JIT 编译通知后,性能分析器可以操作该方法的 IL 代码。使用 Profiler API,性能分析器可以插入、删除或替换 IL 指令。这类似于 Java 代理修改字节码的方式。例如,如果您想测量方法的执行时间,您可以修改 IL 以在方法的开头和结尾分别插入调用来启动和停止计时器。
-
执行转换后的代码: 一旦 IL 被修改,JIT 编译器会将其转换为机器代码。然后应用程序将执行此机器代码,其中包括性能分析器所做的添加。
-
收集和报告数据: 添加的插桩可以收集各种数据,例如方法执行时间或调用计数。然后可以将此数据传递给应用程序性能管理 (APM) 工具,该工具可以根据数据提供见解、可视化和警报。
本质上,使用 CLR Profiler 进行自动插桩就是在运行时修改 .NET 方法的行为。这对于监控、诊断和微调 .NET 应用程序的性能非常宝贵,而不会干扰应用程序的实际源代码。
先决条件
- 对 Docker 和 .NET 的基本了解
- Elastic Cloud
- 您的机器上安装了 Docker(我们建议使用 Docker Desktop)
查看示例源代码
完整的源代码,包括本博客中使用的 Dockerfile,可以在 GitHub 上找到。该存储库还包含 未插桩的相同应用程序。这使您可以比较每个文件并查看差异。
以下步骤将向您展示如何插桩此应用程序并在命令行或 Docker 中运行它。如果您对更完整的 OTel 示例感兴趣,请查看 此处 的 docker-compose 文件,该文件将启动整个项目。
分步指南
本博客假设您拥有一个 Elastic Cloud 帐户 — 如果没有,请按照 说明开始使用 Elastic Cloud。
步骤 1. 基础镜像设置
从 Dockerfile 基础层的 .NET 运行时镜像开始
FROM ${ARCH}mcr.microsoft.com/dotnet/aspnet:7.0. AS base
WORKDIR /app
EXPOSE 8000
在这里,我们正在设置应用程序的运行时环境。
步骤 2. 构建 .NET 应用程序
Docker 的这个功能真是太棒了。在这里,我们使用 SDK 镜像编译我们的 .NET 应用程序。在过去,我们过去是在不同的平台上构建,然后将编译后的代码放入 Docker 容器中。通过这种方式,我们更有信心我们的构建将通过在整个过程中使用 Docker 从开发人员的桌面复制到生产环境。
FROM mcr.microsoft.com/dotnet/sdk:8.0-preview AS build
ARG TARGETPLATFORM
WORKDIR /src
COPY ["login.csproj", "./"]
RUN dotnet restore "./login.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "login.csproj" -c Release -o /app/build
本节确保我们的 .NET 代码已正确还原和编译。
步骤 3. 发布应用程序
构建完成后,我们将发布应用程序
FROM build AS publish
RUN dotnet publish "login.csproj" -c Release -o /app/publish
步骤 4. 准备最终镜像
现在,让我们设置最终的运行时镜像
FROM base AS final
WORKDIR /app
COPY /app/publish
步骤 5. 安装 OpenTelemetry
我们将安装依赖项并下载 OpenTelemetry 自动插桩脚本
RUN apt-get update && apt-get install -y zip curl
RUN mkdir /otel
RUN curl -L -o /otel/otel-dotnet-install.sh https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/download/v0.7.0/otel-dotnet-auto-install.sh
RUN chmod +x /otel/otel-dotnet-install.sh
步骤 6. 配置 OpenTelemetry
指定 OpenTelemetry 应该驻留的位置并执行安装脚本。请注意,需要 ENV OTEL_DOTNET_AUTO_HOME,因为脚本会查找它
ENV OTEL_DOTNET_AUTO_HOME=/otel
RUN /bin/bash /otel/otel-dotnet-install.sh
步骤 7. 其他配置
确保自动插桩和平台检测脚本是可执行的,并运行平台检测脚本。
COPY platform-detection.sh /otel/
RUN chmod +x /otel/instrument.sh
RUN chmod +x /otel/platform-detection.sh && /otel/platform-detection.sh
此平台检测脚本将检查 Docker 构建是否适用于 ARM64,并实施一种解决方法,使 OpenTelemetry 插桩可以在 MacOS 上运行。如果您碰巧在 MacOS M1 或 M2 处理器上本地运行,您会感谢这个脚本。
步骤 8. 入口点设置
最后,设置 Docker 镜像的入口点,以获取 OpenTelemetry 插桩的来源,该插桩设置引导 .NET Profiler 所需的环境变量,然后我们启动我们的 .NET 应用程序
ENTRYPOINT ["/bin/bash", "-c", "source /otel/instrument.sh && dotnet login.dll"]
步骤 9. 使用环境变量运行 Docker 镜像
要构建和运行 Docker 镜像,您通常会遵循以下步骤
构建 Docker 镜像
首先,您需要从 Dockerfile 构建 Docker 镜像。假设 Dockerfile 位于当前目录中,并且您希望将镜像命名/标记为 dotnet-login-otel-image。
docker build -t dotnet-login-otel-image .
运行 Docker 镜像
构建镜像后,您将使用指定的环境变量运行它。为此,docker run 命令与 -e 标志一起用于每个环境变量。
docker run \
-e OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer ${ELASTIC_APM_SECRET_TOKEN}" \
-e OTEL_EXPORTER_OTLP_ENDPOINT="${ELASTIC_APM_SERVER_URL}" \
-e OTEL_METRICS_EXPORTER="otlp" \
-e OTEL_RESOURCE_ATTRIBUTES="service.version=1.0,deployment.environment=production" \
-e OTEL_SERVICE_NAME="dotnet-login-otel-auto" \
-e OTEL_TRACES_EXPORTER="otlp" \
dotnet-login-otel-image
确保
获取 Elastic Cloud 变量
您可以从 Kibana® 的路径下复制端点和令牌
如果您有多个环境变量,您还可以使用带有 docker run --env-file 的环境文件来减少命令的冗长程度。
一旦您启动并运行了此程序,您就可以 ping 您已插桩的服务的端点(在本例中为 /login),并且您应该看到该应用程序出现在 Elastic APM 中,如下所示
它将首先跟踪 SRE 关注的吞吐量和延迟关键指标。
深入研究,我们可以看到我们所有事务的概述。
并查看特定的事务
这里显然有一个异常值,其中一个事务花费了超过 200 毫秒。这很可能是由于 .NET CLR 正在预热。单击 日志,我们看到日志也被带过来。OTel Agent 会自动引入日志,并将其与跟踪相关联。
总结
使用此 Dockerfile,您已将简单的 .NET 应用程序转换为使用 OpenTelemetry 自动插桩的应用程序。这将极大地帮助您了解应用程序性能、跟踪错误并深入了解用户如何与您的软件交互。
请记住,可观察性是现代应用程序开发的关键方面,尤其是在分布式系统中。借助 OpenTelemetry 等工具,理解复杂的系统变得更容易一些。
在本博客中,我们讨论了以下内容
- 如何使用 OpenTelemetry 自动插桩 .NET。
- 通过在 Docker 文件中使用标准命令,可以高效地完成自动插桩,而无需在多个位置添加代码,从而实现可管理性。
- 通过使用 OpenTelemetry 及其对多种语言的支持,DevOps 和 SRE 团队可以轻松地自动插桩他们的应用程序,立即了解整个应用程序堆栈的运行状况,并缩短平均修复时间 (MTTR)。
由于 Elastic 可以支持多种数据摄取方法,无论是使用开源 OpenTelemetry 的自动插桩还是使用其本机 APM 代理的手动插桩,您都可以通过首先关注一些应用程序,然后在稍后以最适合您业务需求的方式在所有应用程序中使用 OpenTelemetry 来规划您到 OTel 的迁移。
开发人员资源
- Elastiflix 应用程序,一个使用 OpenTelemetry 插桩不同语言的指南
- Python:自动插桩,手动插桩
- Java:自动插桩,手动插桩
- Node.js:自动插桩,手动插桩
- .NET:自动插桩,手动插桩
- Go:手动插桩
- 使用 OpenTelemetry 进行插桩的最佳实践
通用配置和用例资源
- 在 Elastic 上使用 OpenTelemetry 的独立性
- 在 Kubernetes 上使用 Elastic 和 OpenTelemetry 实现现代可观察性和安全性
- 使用 OpenTelemetry 和 Elastic 进行日志记录的 3 种模型
- 将免费和开放的 Elastic APM 添加为 Elastic Observability 部署的一部分
- 通过代码中使用 OpenTelemetry API 在 Elastic 中捕获自定义指标
- 使用 OpenTelemetry 和 Elastic 实现可观察性平台的未来保障
- Elastic Observability:为 Kubernetes、OpenTelemetry、Prometheus、Istio 等开放技术而构建
还没有 Elastic Cloud 帐户吗?注册 Elastic Cloud 并试用我上面讨论的自动插桩功能。我很乐意收到您关于使用 Elastic 深入了解您的应用程序堆栈的体验的反馈。
本文中描述的任何特性或功能的发布和时间安排均由 Elastic 自行决定。任何当前不可用的特性或功能可能不会按时交付或根本不会交付。