基于OpenTelemetry实现Java微服务调用链跟踪

createh51个月前 (02-01)技术教程10

本文分享自华为云社区《基于OpenTelemetry实现Java微服务调用链跟踪-云社区-华为云》,作者: 可以交个朋友。

一 背景

随着业务的发展,所有的系统都会走向微服务化体系,微服务进行拆分后,服务的依赖关系变得复杂,如果出现了错误和异常,定位的过程将会变得复杂,一个请求可能需要调用很多个服务,所以微服务架构中,分布式链路跟踪的实现至关重要,去跟进一个请求到底有哪些服务参与,参与的顺序又是怎样的,从而达到每个请求的步骤清晰可见。如何快速查询整个请求链路上的信息并呈现出来是解决排查问题复杂度的根本方法。

二 简介

Java 是世界上最流行的编程语言之一,很多大小项目都是通过Java进行微服务的开发来实现。
本篇博客将以springboot微服务为例,通过使用opentelemetry-java SDK 进行自动埋点以代码无侵入的方式实现微服务的分布式跟踪能力。

三 实践演示

demo项目一共3个service:foo-svc、bar-svc 、loo-svc 。
项目源码可前往:
https://github.com/HFfleming/springboot-trace-demo/tree/autoconfigure

访问效果如下:

3.1 前提条件

已创建k8s 集群,可使用CCE集群平台作为基础环境。

k8s 集群中已安装opentelemetry-collector组件

k8s 集群中已安装jaeger作为分布式跟踪数据展示的平台

3.2 集成opentelemetry-java-instrumentation

OpenTelemetry 提供了 Java agent(
opentelemetry-java-instrumentation)。当附加到应用程序中时,它会修改各种流行库和框架的字节码以捕获遥测数据。可以以多种格式导出遥测数据。还可以通过命令行参数或环境变量配置代理和导出器。
最终结果是无需更改代码即可从 Java 应用程序收集遥测数据。

下载otel-java jar包并添加到容器镜像中

前往官方仓库
https://github.com/open-telemetry/opentelemetry-java-instrumentation下载
opentelemetry-javaagent.jar

通过环境变量配置java agent和otlp导出器

  • 通过环境变量的形式配置java agent:ENV JAVA_TOOL_OPTIONS="-javaagent:/usr/app/opentelemetry-javaagent.jar"
  • 服务名称: ENV OTEL_SERVICE_NAME="foo-svc"
  • 使用otlp协议的导出器:ENV OTEL_TRACES_EXPORTER="otlp"
  • 关闭java agent的指标 otlp导出器: ENV OTEL_METRICS_EXPORTER="none"
  • 关闭java agent的日志 otlp导出器: ENV OTEL_LOGS_EXPORTER="none"
  • 指定OTLP导出器的端点,跨ns的场景下建议写上otel的ns:ENV OTEL_EXPORTER_OTLP_ENDPOINT="http://opentelemetry-collector.tracing.svc.cluster.local:4317"
  • 除了环境变量的形式,也可通过jvm参数形式进行agent和导出器的配置。
    详细配置或者欲开启更多导出信息可参考: https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure

容器镜像制作

建议重新制作镜像,将opentelemetry-javaagent等otlp基础配置打包在镜像中。后续如果有变动,也可通过deployment中env字段进行修改覆盖。

镜像Dockerfile文件可参照如下:

#基于官方的Maven镜像
FROM maven:3.8.7-openjdk-18-slim AS build

#将本地代码复制到Docker容器中的 /usr/src/app 目录下
COPY src /usr/src/foo-app/src
COPY pom.xml /usr/src/foo-app
COPY opentelemetry-javaagent.jar /usr/src/foo-app

# 在容器的 /usr/src//foo-app 目录下,运行mvn clean package 命令,构建项目
RUN mvn -f /usr/src/foo-app/pom.xml clean package

# 使用官方的openjdk 镜像作为基础镜像
FROM  openjdk:19-jdk-slim

# 将打包生成的jar文件复制到容器中
COPY --from=build /usr/src/foo-app/target/*.jar  /usr/app/foo-app.jar
COPY --from=build /usr/src/foo-app/opentelemetry-javaagent.jar /usr/app/opentelemetry-javaagent.jar

# 声明服务运行在8080端口
EXPOSE 8080

# 通过环境变量的形式配置java agent并且通过环境变量传递配置属性
ENV JAVA_TOOL_OPTIONS="-javaagent:/usr/app/opentelemetry-javaagent.jar"
# 服务的k8s servicename
ENV OTEL_SERVICE_NAME="foo-svc"
# 使用的是otlp协议的导出器
ENV OTEL_TRACES_EXPORTER="otlp"
# 关闭java agent的指标 otlp导出器
ENV OTEL_METRICS_EXPORTER="none"
## 关闭java agent的日志 otlp导出器
ENV OTEL_LOGS_EXPORTER="none"
# 指定OTLP导出器的端点,跨ns的场景下建议写上otel的ns
ENV OTEL_EXPORTER_OTLP_ENDPOINT="http://opentelemetry-collector.tracing.svc.cluster.local:4317"

#指定docker容器的启动命令
ENTRYPOINT ["java", "-jar","/usr/app/foo-app.jar"]

镜像推送至镜像仓库,可使用SWR容器镜像仓库

docker build 构建完镜像后,然后docker push 至镜像仓库。
本人demo项目镜像如下,可供读者调试使用:
foo-svc:
swr.cn-north-4.myhuaweicloud.com/k8s-solution/foo-svc:v2

bar-svc:
swr.cn-north-4.myhuaweicloud.com/k8s-solution/bar-svc:v2

loo-svc:
swr.cn-north-4.myhuaweicloud.com/k8s-solution/loo-svc:v2

在k8s集群中部署demo项目

其中loadgenerator服务是个客户端工具用于访问demo项目。访问信息如下:

相比之前没有集成
opentelemetry-javaagent.jar ,访问信息请求头多了traceparent信息,很明显该信息就是分布式跟踪所需要使用到的

3.3 OpenTelemetry配置遥测数据的接受和导出

在上述环境变量中,通过otlp-grpc协议进行java微服务遥测数据导出的。所以在opentelemetry-collector中的receivers接收器配置中需要配置otlp grpc规则进行数据的接受:

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: ${env:MY_POD_IP}:4317

otel接受到数据后,需要将数据处理后进行导出。导出后端可以是jaeger,通过jaeger进行分布式跟踪数据的展示,需要需要在opentelemery-collector中配置exporter导出器

exporters:
  debug: {}  #导出器配置log,可记录导出行为
  otlp:
    endpoint: jaeger-collector.hu.svc.cluster.local:4317 #jaeger的otlp-grpc端口
    tls:
      insecure: true

需要注意此处导出器后端jaeger使用的协议为otlp,如果jaeger-collector service未配置该端口,则会导出失败,建议检查jaeger相关service的配置。

- name: otlp-grpc
  port: 4317
  protocol: TCP
  targetPort: 4317

通过pipeline启用otel采集器中配置的各种组件。上面配置了接收器和导出器,如果不在pipeline中声明,则不会启用该组件。启用方式参考:

service: # 用于根据接收器、处理器、导出器和扩展部分中的配置来配置收集器中启用的组件
  extensions:
  - health_check
  pipelines:
    traces:
      exporters:
      - debug
      - otlp
      processors:
      - memory_limiter
      - batch
      receivers:
      - otlp

完整配置参考如下,这些配置以configmap形式挂载到otel-collector容器中使用。

apiVersion: v1
kind: ConfigMap
metadata:
  name: opentelemetry-collector
  namespace: tracing
data:
  relay: |
    exporters:
      debug: {}
      otlp:
        endpoint: jaeger-collector.hu.svc.cluster.local:4317
        tls:
          insecure: true
    extensions:
      health_check:
        endpoint: ${env:MY_POD_IP}:13133

    processors:
      batch: {}
      memory_limiter:
        check_interval: 5s
        limit_percentage: 80
        spike_limit_percentage: 25

    receivers:
      otlp:
        protocols:
          grpc:
            endpoint: ${env:MY_POD_IP}:4317

    service:
      extensions:
      - health_check
      pipelines:
        traces:
          exporters:
          - debug
          - otlp
          processors:
          - memory_limiter
          - batch
          receivers:
          - otlp

      telemetry:
        metrics:
          address: ${env:MY_POD_IP}:8888

配置更新后,重启otel-collector容器。查看otel容器日志可以看到otel已经以配置的规则进行工作。

3.4 Jaeger查看调用链跟踪数据

访问jaeger UI,UI端口为16686。可以看到jaeger已经接收到trace信息,目前已有4条trace,每条trace均有8个span信息。

查看详细span信息,不仅可以看到服务级别的调用,还能看到方法级别的调用,以及方法级别的耗时。

关注#华为云开发者联盟# 点击下方,第一时间了解华为云新鲜技术~

华为云博客_大数据博客_AI博客_云计算博客_开发者中心-华为云

相关文章

如何通过Serverless提高 Java 微服务治理效率?

简介: 在业务初期,因人手有限,想要快速开发并上线产品,很多团队使用单体的架构来开发。但是随着公司的发展,会不断往系统里面添加新的业务功能,系统越来越庞大,需求不断增加,越来越多的人也会加入到开发团队...

Java:Java中的微服务(java微服务包括什么)

  如果你想使用Java中的云原生微服务快速实现大规模可扩展性,那么不需要重新发明轮子。一些创新工具可以帮助你。通过Java培训课程,在Java(软件开发中最常用的编程语言)方面打下坚实的基础,更好地...

3 个主流 Java 微服务框架的特点分析

本文我们简单聊聊当下主流的 3 个 Java 微服务框架,看看各自的特点,下面和千锋广州小编一起来看看吧!1. Spring and Spring BootimageSpring Boot 在 Jav...

开源微服务编排框架:Netflix Conductor

本文主要介绍netflix conductor的基本概念和主要运行机制。一 简介netflix conductor是基于JAVA语言编写的开源流程引擎,用于架构基于微服务的流程。它具备如下特性:允许创...

5个支持微服务体系结构的Java框架

在过去的五年中,随着专门为支持新的微服务而构建的技术的发展,该行业出现了爆炸式的发展。但这并不意味着它们最适合每个人的需要。事实上,与通常在考虑技术堆栈的情况下开发的Monolith不同,微服务体系结...