java后端对接apm常见问题总结

一只会飞的鱼儿 2天前 ⋅ 4 阅读
ad

1、OpenTelemetry 字节码增强与 Redisson 3.5.0 不兼容导致的。

方案一:临时绕过(快速恢复服务)

如果需要先让服务跑起来,可以直接排除 Redisson 的 OpenTelemetry 增强:
  • 在 JVM 启动参数中添加排除规则
     
    -Dotel.instrumentation.redisson.enabled=false
    
    这个参数会禁用 OpenTelemetry 对 Redisson 的自动埋点,避免字节码冲突。
  • 检查依赖冲突:确认 pom.xml 中没有同时引入 opentelemetry-sdkopentelemetry-agent 相关的依赖,避免 SDK 和 Agent 双重增强导致字节码混乱。

方案二:升级兼容版本(推荐长期方案)

Redisson 3.5.0 是一个非常老旧的版本(2016 年发布),和现代 OpenTelemetry 版本存在天然的兼容性鸿沟。
  • 升级 Redisson 版本:建议升级到 3.17.x 以上版本(OpenTelemetry 官方文档明确支持 Redisson 3.0+,但 3.17 以上修复了大量字节码兼容性问题):
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.25.0</version> <!-- 选择稳定版 -->
</dependency>
  • 使用匹配的 OpenTelemetry Agent 版本:升级 Redisson 后,同步更新 OpenTelemetry Agent 到最新稳定版,确保两者的增强逻辑兼容。

 

2、OpenTelemetry Java Agent 对 Spring 定时任务(spring-scheduling)做字节码增强时,把类弄坏了 → JVM 直接拒绝加载类

这个 100% 是 OpenTelemetry Java Agent 字节码增强 Bug

OpenTelemetry Agent 在动态修改 Spring 内部类 DelegatingErrorHandlingRunnable 的字节码时,破坏了 JVM 的构造器 + try 块的字节码校验规则,直接触发 JVM 类加载校验失败,Spring 容器还没启动完成就崩溃

最快立刻修复(优先用这个,马上启动成功)

直接在 JVM 启动参数 里添加全局禁用 + 针对性排除,彻底绕开有问题的增强逻辑:
# 核心必加参数
-Dotel.instrumentation.spring-scheduling.enabled=false

加上pom.xml引入下面的,解决成功

    <!-- OpenTelemetry API -->
    <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-api</artifactId>
        <version>1.24.0</version>
    </dependency>
    
    <!-- OpenTelemetry 注解支持 -->
    <dependency>
        <groupId>io.opentelemetry.instrumentation</groupId>
        <artifactId>opentelemetry-instrumentation-annotations</artifactId>
        <version>1.24.0</version>
    </dependency>
</dependencies>

永久根治方案(长期稳定)

2.1、降级 / 锁定 OpenTelemetry Agent 稳定版本,最新版 Agent 反而有兼容性问题,建议降级到 1.32.0(兼容性最好,无该 VerifyError)

# 下载稳定版Agent
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v1.32.0/opentelemetry-javaagent.jar

2.2、不要同时混合「Agent + SDK 注解」

  • 只用 Agent 零代码埋点,就移除所有手动 opentelemetry-sdk、api 依赖
  • 只用代码注解埋点,就完全去掉 -javaagent 参数二者绝对不能混用,会双重字节码增强,必出 VerifyError

2.3、版本匹配检查

  • Spring Boot 2.x → 推荐 OTel Agent 1.29~1.35
  • Spring Boot 3.x → 推荐 OTel Agent 2.x+
  • JDK 8 避免使用最新 2.x 系列 Agent,兼容性极差

3、OpenTelemetry Java Agent 的配置必须在 JVM 启动参数中提供,它不会读取 Spring Boot 的配置中心(Nacos/Apollo 等),因为:

  • Agent 在 Spring Boot 之前加载:Agent 通过 -javaagent 参数在 JVM 启动时加载,此时 Spring 容器还未初始化
  • 配置中心是应用层:Nacos/Apollo 等配置中心由 Spring Cloud 在应用启动后才加载

解决方案

方案一:通过 JVM 启动参数传入(推荐)

将 Agent 配置转换为系统属性,通过启动参数传入:

java -javaagent:/path/to/opentelemetry-javaagent.jar \
     -Dotel.service.name=Sit-backstage \
     -Dotel.resource.attributes="deployment.environment=apm_20250421_141105_sit,service.instance.id=apm_20250421_141105_sit,service.version=1.0" \
     -Dotel.instrumentation.redisson.enabled=false \
     -Dotel.instrumentation.spring-scheduling.enabled=false \
     -Dotel.instrumentation.spring-core.enabled=false \
     -Dotel.exporter.otlp.endpoint="http://localhost:9013" \
     -Dotel.exporter.otlp.protocol=grpc \
     -Dotel.exporter.otlp.timeout=10s \
     -Dotel.traces.exporter=otlp \
     -Dotel.metrics.exporter=none \
     -Dotel.logs.exporter=none \
     -jar your-app.jar

方案二:使用配置文件(最简便)

将配置写入 otel-config.properties 文件:

# otel-config.properties
otel.service.name=Sit-backstage
otel.resource.attributes=deployment.environment=apm_20250421_141105_sit,service.instance.id=apm_20250421_141105_sit,service.version=1.0
otel.instrumentation.redisson.enabled=false
otel.instrumentation.spring-scheduling.enabled=false
otel.instrumentation.spring-core.enabled=false
otel.exporter.otlp.endpoint=http://localhost:9013
otel.exporter.otlp.protocol=grpc
otel.exporter.otlp.timeout=10s
otel.traces.exporter=otlp
otel.metrics.exporter=none
otel.logs.exporter=none

启动时指定配置文件:

java -javaagent:/path/to/opentelemetry-javaagent.jar \
     -Dotel.javaagent.configuration-file=/path/to/otel-config.properties \
     -jar your-app.jar

方案三:配置中心 + 动态生成配置文件(适合复杂场景)

如果必须使用配置中心管理,可以在启动脚本中动态读取配置并生成文件:

#!/bin/bash
# 从配置中心读取配置并生成 otel.properties
curl -s "http://nacos-server:8848/nacos/v1/cs/configs?dataId=otel-config&group=DEFAULT_GROUP" > /tmp/otel-config.properties

# 启动应用
java -javaagent:/path/to/opentelemetry-javaagent.jar \
     -Dotel.javaagent.configuration-file=/tmp/otel-config.properties \
     -jar your-app.jar

 

4、agent采集不到 spring gateway这种异步网关的数据问题

OpenTelemetry Java Agent 完全可以采集 Spring Cloud Gateway 的数据,但需要注意几个关键点:

OpenTelemetry Agent 对 Spring Gateway 的支持

已支持的组件

OpenTelemetry Java Agent 内置了对 Spring Cloud Gateway 的自动埋点:

  • WebFlux instrumentation:Spring Gateway 基于 WebFlux(响应式编程),Agent 会自动拦截
  • Netty instrumentation:Gateway 底层使用 Netty,Agent 也会采集
  • HTTP 客户端/服务端:请求链路自动追踪

️ 可能遇到的问题

4.1. 异步链路的 Span 关联问题

Spring Gateway 是响应式异步网关,Span 的传播需要通过 Mono/Flux 的上下文:

// Agent 会自动处理,但如果你手动创建 Span,需要注意
@WithSpan
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    // Agent 会自动关联父 Span
    return chain.filter(exchange);
}

4.2. 部分高级特性可能未覆盖

  • 自定义 GatewayFilter 的内部方法调用
  • 动态路由刷新时的配置加载
  • Hystrix/Resilience4j 熔断器的内部细节

4.3. 性能开销

响应式网关本身就很轻量,Agent 的字节码增强可能带来额外开销(通常 <5%)

建议配置

在 Agent 配置中启用 Gateway 相关 instrumentations

# otel-agent.properties
otel.instrumentation.spring-webflux.enabled=true
otel.instrumentation.netty.enabled=true
otel.instrumentation.webflux-server.enabled=true

# 如果使用了 Resilience4j 熔断器
otel.instrumentation.resilience4j.enabled=true

排除不必要的采集(减少 Span 数量)

# 如果你的 Gateway 只做转发,不需要采集静态资源
otel.instrumentation.webflux.exclude-patterns=/actuator/**,/health/**,/favicon.ico

验证是否采集成功

启动后检查以下日志:

# 查看 Agent 加载的 instrumentations
java -javaagent:/path/to/opentelemetry-javaagent.jar \
     -Dotel.javaagent.debug=true \
     -jar gateway.jar 2>&1 | grep -i "spring-webflux\|netty\|gateway"

你会看到类似输出:

[otel.javaagent 2026-04-21 14:00:00:000 +0800] [main] DEBUG 
Instrumentation spring-webflux-5.0 enabled
Instrumentation netty-4.0 enabled

实际测试建议

你可以在 Gateway 中加一个简单的过滤器,观察 Trace 是否完整:

@Component
public class TraceTestFilter implements GlobalFilter, Ordered {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("Gateway processing request: {}", exchange.getRequest().getPath());
        return chain.filter(exchange);
    }
    
    @Override
    public int getOrder() {
        return -100;
    }
}

然后在 Webfunny APM 平台查看:

  1. 是否有 Gateway 服务的 Span
  2. 调用链是否包含 Gateway → 后端服务 的完整链路
  3. 响应时间是否符合预期

总结

OpenTelemetry Java Agent 完全支持 Spring Cloud Gateway,你遇到的采集问题可能是:

  • Agent 版本过低(你的 1.33.5 或 2.22 都支持)
  • 配置中禁用了 spring-webflux instrumentation
  • 响应式上下文的传播问题(通常是框架版本兼容性)
  • 采样率设置过低(默认 100%,检查是否被修改)

5、针对基于 RPC 调用的核心应用,OpenTelemetry Agent 的配置确实有特殊之处。以下是关键注意点:(具体参考:http://blog.webfunny.cn/blog/post/361)

RPC 调用的特殊配置

5.1. RPC 协议识别

OpenTelemetry Agent 需要正确识别 RPC 协议类型,常见协议:

RPC 框架 Agent Instrumentation 配置项
gRPC grpc-1.6 otel.instrumentation.grpc.enabled=true
Dubbo dubbo-2.7 otel.instrumentation.dubbo.enabled=true
Thrift thrift otel.instrumentation.thrift.enabled=true
Motan motan otel.instrumentation.motan.enabled=true
RSocket rsocket otel.instrumentation.rsocket.enabled=true

在你的配置中需要明确启用

# otel-agent.properties

# RPC 框架(根据实际情况选择)
otel.instrumentation.grpc.enabled=true
otel.instrumentation.dubbo.enabled=true
otel.instrumentation.grpc.experimental-span-attributes=true

# 如果用了 Spring Cloud Stream / RabbitMQ / Kafka 做 RPC
otel.instrumentation.spring-rabbit.enabled=true
otel.instrumentation.kafka.enabled=true

关于Webfunny

Webfunny专注于前端监控系统,前端埋点系统的研发。 致力于帮助开发者快速定位问题,帮助企业用数据驱动业务,实现业务数据的快速增长。支持H5/Web/PC前端、微信小程序、支付宝小程序、UniApp和Taro等跨平台框架。实时监控前端网页、前端数据分析、错误统计分析监控和BUG预警,第一时间报警,快速修复BUG!支持私有化部署,Docker容器化部署,可支持千万级PV的日活量!

  点赞 0   收藏 0
  • 一只会飞的鱼儿
    共发布72篇文章 获得8个收藏
全部评论: 0