霸王餐API日志链路追踪:OpenTelemetry自动注入与SkyWalking对比

一、业务痛点
吃喝不愁“霸王餐”API集群日调用量 8 亿次,高峰期 12w qps。一次“下单→风控→券核销→商家回调”链路跨越 7 个服务、3 个消息队列、2 个 DB。旧日志方案只有 RequestId,无法回答:

  1. 哪台容器慢?
  2. 哪段代码抛异常?
  3. 网络抖动还是 GC 抖动?

目标:零代码侵入、秒级采样、兼容现有 ELK,同时在 SkyWalking 与 OpenTelemetry 之间给出可落地的二选一方案。


在这里插入图片描述

二、技术选型指标

维度SkyWalkingOpenTelemetry备注
Agent 字节码注入自带依赖 javaagent均支持
协议SW6 私有W3C Trace-ContextOT 更通用
后端存储ES/H2/BanyanDBES/Jaeger/自定义公司统一 ES
采样策略静态 QPS动态概率 + TailOT 更细
dashboard 告警内置需 GrafanaSW 省工作量

三、OpenTelemetry 自动注入实战

3.1 依赖版本

<properties>
<opentelemetry.version>1.32.0</opentelemetry.version>
</properties>
<dependency>
<groupId>io.opentelemetry.javaagent</groupId>
<artifactId>opentelemetry-javaagent</artifactId>
<version>${opentelemetry.version}</version>
</dependency>

3.2 Dockerfile 一行注入

COPY opentelemetry-javaagent.jar /opt/agent.jar
ENV JAVA_TOOL_OPTIONS="-javaagent:/opt/agent.jar \
  -Dotel.service.name=ba霸王餐-order \
  -Dotel.traces.exporter=otlp \
  -Dotel.exporter.otlp.endpoint=http://otel-collector:4317 \
  -Dotel.instrumentation.common.default-enabled=true \
  -Dotel.metrics.exporter=none"

3.3 自定义 Span:记录“券核销”耗时

package cn.juwatech.bawang.canal.service;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
@Service
public class CouponService {
private static final Tracer tracer =
GlobalOpenTelemetry.getTracer("cn.juwatech.bawang.canal");
public void consume(String couponId, String userId) {
Span span = tracer.spanBuilder("coupon.consume")
.setAttribute("coupon.id", couponId)
.setAttribute("user.id", userId)
.startSpan();
try (Scope ignored = span.makeCurrent()) {
// 业务逻辑
doConsume(couponId);
span.setAttribute("result", "ok");
} catch (Exception e) {
span.recordException(e);
throw e;
} finally {
span.end();
}
}
}

3.4 采样规则动态配置

# otel-collector-config.yaml
processors:
probabilistic_sampler:
sampling_percentage: 5
tail_sampling:
policies:
- name: slow-span
type: latency
latency: {threshold_ms: 500}

四、SkyWalking 8.9 接入实录

4.1 镜像层打包

FROM apache/skywalking-java-agent:8.9.0-java11
COPY app.jar /app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

4.2 自定义层(@Trace 增强)

package cn.juwatech.bawang.canal.service;
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.apache.skywalking.apm.toolkit.trace.Tag;
import org.springframework.stereotype.Service;
@Service
public class RiskService {
@Trace(operationName = "risk.evaluate")
@Tag(key = "score", value = "returnedObj.score")
public RiskResult evaluate(String userId) {
// 风控逻辑
return new RiskResult(computeScore(userId));
}
}

4.3 日志绑定 TraceId

<configuration>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}
      [%tid] - %msg%n</pattern>
    </encoder>
  </appender>
    <root level="INFO">
    <appender-ref ref="CONSOLE"/>
  </root>
</configuration>

[%tid]apm-toolkit-logback-1.x 提供,直接输出 SkyWalking TraceId。


五、链路对比压测数据
环境:4C8G × 30 容器,2k 并发,持续 20min。

指标OpenTelemetrySkyWalking
CPU 增加+6%+5%
延迟 P99+3 ms+2 ms
存储量/亿条260 GB180 GB
查询 Trace 完整率99.2%99.5%

结论:SW 存储压缩率更高;OT 在跨云、多语言场景更灵活。


六、采样与存储优化

6.1 OpenTelemetry Collector 级联

receivers:
otlp:
protocols:
grpc:
processors:
batch:
timeout: 1s
send_batch_size: 1024
exporters:
elasticsearch:
endpoints: ["http://es:9200"]
index: "otel-v2-%{+yyyy.MM.dd}"
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [elasticsearch]

6.2 SkyWalking ES 模板冷热分离

PUT _ilm/policy/sw7-trace
{
"policy": {
"phases": {
"hot": {"actions": {"rollover": {"max_size": "30GB"}}},
"warm": {"actions": {"shrink": {"number_of_shards": 1}}},
"cold": {"actions": {"searchable_snapshot": {"snapshot_repository": "backup"}}}
}
}
}

七、代码级排障案例

场景:用户反馈“霸王餐下单 502”。
步骤

  1. 在 Grafana 搜索 http.status_code=502
  2. 定位到 ba霸王餐-gateway 实例 10.244.6.89
  3. 点击 Trace,发现 risk.evaluate Span 耗时 28s;
  4. 查看同 Span 的 score Tag,发现 Redis 命令 EVALSHA 超时;
  5. 回滚 Redis Lua 脚本,502 归零。

全过程 3 分钟,无需登录容器。


八、灰度与回滚策略

  1. 按 Kubernetes Namespace 灰度:
    otel-collectorsw-oap 双跑,通过注解 sidecar.skywalking.enable=false 一键关闭。
  2. 回滚:
    删除 JAVA_TOOL_OPTIONS 中的 -javaagent 即可,应用无感知。

九、后续演进

  1. 将 OpenTelemetry Metrics 接入 Prometheus,统一告警。
  2. eBPF + OT 实现网络 RTT 级别观测。
  3. 使用 SkyWalking Satellite 替换 sidecar,降低 20% CPU。

本文著作权归吃喝不愁app开发者团队,转载请注明出处!