针对基于 RPC 调用的应用,OpenTelemetry Agent的配置

一只会飞的鱼儿 昨天 ⋅ 1 阅读
ad

针对基于 RPC 调用的核心应用,OpenTelemetry Agent 的配置确实有特殊之处。以下是关键注意点:

RPC 调用的特殊配置

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

2. 跨服务上下文传播

RPC 调用需要正确的 Propagation Format,这是最常见的坑:

# 传播格式(根据 RPC 框架选择)
otel.propagators=tracecontext,baggage,b3

# 如果 RPC 框架使用自定义 Header,需要配置
otel.propagators=b3  # Zipkin B3 格式
otel.propagators=w3c # W3C TraceContext(推荐)

常见场景

  • Dubbo:使用 attachment 传递 context,Agent 会自动处理
  • gRPC:使用 metadata 传递,需要 otel.instrumentation.grpc.enabled=true
  • 自定义 RPC:可能需要手动传播 context

3. Span 命名规范

RPC 调用的 Span 命名很重要,影响 APM 平台的展示:

# 启用 RPC 语义约定
otel.instrumentation.grpc.experimental-span-attributes=true

# 自定义 Span 名称(如果需要)
# Agent 会自动生成类似:POST /service/method

4. 性能优化配置

RPC 调用通常是高频操作,需要注意

# 采样率(生产环境建议降低)
otel.traces.sampler=parentbased_traceidratio
otel.traces.sampler.arg=0.1  # 10% 采样率

# 批量导出配置(减少网络开销)
otel.bsp.schedule.delay=5000        # 5秒刷新一次
otel.bsp.max.queue.size=2048        # 最大队列
otel.bsp.max.export.batch.size=512  # 批量大小

# 如果 RPC 调用很频繁,增加队列
otel.bsp.max.queue.size=4096

5. 错误处理

RPC 调用的异常需要正确记录:

# 记录异常信息到 Span
otel.instrumentation.experimental.span-exception-event-enabled=true

# 如果 RPC 框架使用特定异常,确保被捕获
# 例如 Dubbo 的 RpcException

完整的 RPC 应用配置示例

# otel-rpc-agent.properties

# ===== 基础配置 =====
otel.service.name=core-rpc-service
otel.resource.attributes=deployment.environment=prod,service.version=2.1.0

# ===== RPC 框架配置 =====
# gRPC
otel.instrumentation.grpc.enabled=true
otel.instrumentation.grpc.experimental-span-attributes=true

# Dubbo(如果使用)
otel.instrumentation.dubbo.enabled=true
otel.instrumentation.dubbo.consumer.enabled=true
otel.instrumentation.dubbo.provider.enabled=true

# ===== 上下文传播 =====
otel.propagators=tracecontext,baggage,b3

# ===== 采样配置 =====
otel.traces.sampler=parentbased_traceidratio
otel.traces.sampler.arg=0.1

# ===== 导出配置 =====
otel.traces.exporter=otlp
otel.exporter.otlp.endpoint=http://192.168.17.100:9013
otel.exporter.otlp.protocol=grpc
otel.exporter.otlp.timeout=10s

# 批量导出优化
otel.bsp.schedule.delay=5000
otel.bsp.max.queue.size=4096
otel.bsp.max.export.batch.size=512

# ===== 排除配置 =====
# 排除健康检查等高频调用
otel.instrumentation.grpc.exclude-patterns=/grpc.health.v1.Health/*

# ===== 其他 =====
otel.metrics.exporter=none
otel.logs.exporter=none

特殊场景处理

场景 1:RPC 调用跨异步边界

如果你的 RPC 调用在异步线程中:

// 需要手动传播 Context
Span span = tracer.spanBuilder("async-rpc-call").startSpan();
try (Scope scope = span.makeCurrent()) {
    // RPC 调用
    CompletableFuture.runAsync(() -> {
        // 在异步线程中,Context 会自动传播(Agent 会处理)
        rpcClient.call();
    });
} finally {
    span.end();
}

场景 2:自定义 RPC 协议

如果使用了自研 RPC 框架:

// 需要在代码中手动埋点
@WithSpan("custom-rpc-call")
public Response rpcCall(Request req) {
    // 手动添加属性
    Span.current().setAttribute("rpc.system", "custom");
    Span.current().setAttribute("rpc.service", req.getService());
    Span.current().setAttribute("rpc.method", req.getMethod());
    return rpcClient.invoke(req);
}

场景 3:RPC 熔断/限流

如果使用了熔断器(如 Resilience4j):

otel.instrumentation.resilience4j.enabled=true

# 或者 Hystrix(如果还在用)
otel.instrumentation.hystrix.enabled=true

验证清单

启动后检查:

  • Span 命名是否正确
    • 应该看到类似 POST /com.example.UserService/getUser
    • 而不是简单的 HTTP POST
  • 跨服务链路是否完整
     
    Gateway → Service A (RPC) → Service B (RPC) → Database
  • 上下文传播是否正常
     
    # 查看日志中的 traceId 是否一致
    curl http://gateway/api/test  # 查看各服务日志的 traceId
  • 性能影响是否可接受
     
    # 对比接入 Agent 前后的 RPC 延迟
    # 通常在 1-3ms 以内是可接受的

常见问题

Q: RPC 调用的 TraceId 不一致?
A: 检查 otel.propagators 配置,确保客户端和服务端使用相同的传播格式。

Q: RPC Span 数量太多?
A: 降低采样率 otel.traces.sampler.arg=0.1,或排除特定方法。

Q: RPC 调用异常没有被记录?
A: 启用 otel.instrumentation.experimental.span-exception-event-enabled=true

关于Webfunny

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

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