Distributed Tracing
(部分: 技术和基础设施)
简短摘要
分布式跟踪提供了以下问题的答案:通过网关,API,队列,DB,外部提供商(PSP/游戏工作室)的请求路径在何处以及为何浪费时间。OpenTelemetry(OTel)是开放的SDK/Agent/协议标准,结合了预告片,度量和日志。在iGaming中,它是保持p95/p99,快速本地化支付问题并在高峰锦标赛之前识别"瓶颈"的基本工具。
1) OTel概念
Trace-完整的交易路径(存款、出价、出价)。
Span-工作区(HTTP-handler、SQL查询、队列/提供程序调用)。
Attributes是具有零件('net。peer.name`, `db.system`, `psp.route`).
事件-即时事件(转发、定时、缓存错误)。
链接是与其他轨道的连接(对于async/queue至关重要)。
资源-流程元数据: '服务。name`, `service.version`, `deployment.environment`, `cloud.region`.
2)上下文的宣传
使用W3C跟踪上下文:
traceparent: 00-<trace_id>-<span_id>-01 tracestate:...
另外-对于安全钥匙(例如"tenant","route"),不要将PII放在那里。
在哪里刺穿上下文:API网关→内部RPC →生产者排队→用户→外部HTTP(PSP/提供商)。
3)语义约定(强制性最低限度)
HTTP/RPC: `http.method`, `http.route`, `http.status_code`.
DB/缓存: 'db。system` (`mysql`/`postgresql`/`redis`), `db.statement"(伪装),"db。operation`.
队列: 'messaging。system` (`kafka`/`rabbitmq`), `messaging.destination`, `messaging.operation` (`send`/`process`).
付款:'psp。route`, `psp.provider`, `payment.id'(化名),'amount','currency'。
iGaming域: '游戏。provider`, `game.session_id` (hash), `player.id_hash`.
单一分类法→ dashbords的可比性和快速的原因搜索。
4)Sampling: 如何不淹死在数据中
基于头部(在查询输入处)
简单,便宜;适合一般流动。
减-您可以丢失"有趣"的缓慢/错误的轨道。
Tail-based (в Collector)
该决定是在完成后做出的:我们只保留错误/缓慢/重要部分(VIP/付款)。
非常适合prod负荷:在高信息性的情况下,大幅降低成本。
- Head: 5-10%用于"背景"覆盖。
- Tail: 100%错误+p95+缓慢+支付路线/金丝雀发行。
5) OpenTelemetry Collector拓扑
Agent sidkar(在每个节点/子节点上):本地接收、最小缓冲区、导出到聚合器。
网关(集群):尾部采样,路由,富集,导出到Tempo/Jaeger/Zipkin/OTLP。
示例: tail-sampling (YAML片段)
yaml processors:
tailsampling:
decision_wait: 5s policies:
- name: errors type: status_code status_code:
status_codes: [ ERROR ]
- name: slow_p95 type: latency latency:
threshold_ms: 250
- name: payments type: string_attribute string_attribute:
key: service. name values: [ "payments-api", "payments-worker" ]
6)与指标和日志的相关性
在每个日志条目中添加"trace_id"/"span_id"。
将潜伏度度量存储为直方图,并启用exemplars-指向代表"trace_id"的链接,以从p95框跳到特定的路径。
发行注释(Git SHA,图表版本)-作为活动/标签。
7)工具化(语言和自动代理)
Go(手动+汽车)
go tp:= sdktrace. NewTracerProvider(
sdktrace. WithBatcher(exporter),
sdktrace. WithResource(resource. NewWithAttributes(
semconv. SchemaURL,
semconv. ServiceName("payments-api"),
)),
)
otel. SetTracerProvider(tp)
ctx, span:= tracer. Start(ctx, "Deposit")
defer span. End()
span. SetAttributes(
attribute. String("psp. route","pspX"),
attribute. String("currency","EUR"),
)
Java
自动代理'-javaagent: opentelemetry-javaagent。jar',通过env的config("OTEL_SERVICE_NAME","OTEL_EXPORTER_OTLP_ENDPOINT")。
手动-弓形位置注释/工具(JDBC池、缓存)。
Node.js / Python
带有SDK+插件的自动工具(Express/FastAPI/celery)。
对于队列,是制作人/消费者的包装纸,以提供"消息传递"。
8)队列和async: 正确的睡眠
制片人("send"):span发送到拓扑/队列。
消费者("process"):从链接到生产者的span 处理消息的新span(保留因果关系而无需共享"trace_id")。
属性: 'messaging。kafka.partition`, `messaging.rabbitmq.routing_key`, `messaging.message_id`.
在回溯中-事件"回溯",尝试计数器。
9) DB/缓存和 N+1
启用DB驱动程序预告,将相同类型的请求分组到batchi中。
对于Redis/缓存,"缓存"属性。hit`/`cache.miss`.
将"繁重"的查询发送到单独的睡眠-可以看到p99的位置。
10)外部提供商: PSP/游戏工作室
包裹HTTP客户端: 'psp。provider`, `psp.route`, `timeout_ms`, `attempt`.
编写代码/错误类型,但不编写PII(卡号、令牌)。
通过"duration"、"error-rate"比较工作室/路线。
11) Frontend和RUM
OTel Web SDK: `page_view`, `resource_load`, `xhr`.
将"traceparent"刺入后台,以缝制UI → API → DB skvoz的用户路径。
按地理/网络提供商进行细分-可选标签。
12)安全和PII
掩盖字段('db."通过编辑",哈希化"player_id"。
数据区域:"pii=true","region=EU/TR/LATAM"。
控制对付款跟踪的访问(基于角色)。
WORM/Retention:敏感跟踪的保留时间,策略删除。
13)生产力和成本
策略提示采样:"错误+缓慢+付款+金丝雀发行版"。
Downsampling直方图指标,激进的重复数据消除日志.
基数约束:不要将"user_id"标记为度量标签。
Collector中的缓冲区/蹦床,OTLP压缩。
14) Dashbords和分析
服务地图:服务依赖性,错误/潜伏着色。
Release compare:稳定vs金丝雀修订(p95, error-rate, payments conv)。
Top slow traces:在"/deposit"路线上,在PSP/区域上切口。
Queue lag:深度延迟的轨道。
15) Collector配置示例
Pipelines(度量/traces/logi,片段)
yaml receivers:
otlp: { protocols: { http: {}, grpc: {} } }
processors:
batch:
memory_limiter:
limit_mib: 1024 spike_limit_mib: 256 attributes/payments:
actions:
- key: "psp. provider"
action: insert value: "pspX"
exporters:
otlp/traces: { endpoint: tempo:4317, tls: { insecure: true } }
otlp/metrics:{ endpoint: prometheus-otlp:4317, tls: { insecure: true } }
otlp/logs: { endpoint: loki-otlp:4317, tls: { insecure: true } }
service:
pipelines:
traces:
receivers: [ otlp ]
processors: [ memory_limiter, batch, tailsampling ]
exporters: [ otlp/traces ]
metrics:
receivers: [ otlp ]
processors: [ batch ]
exporters: [ otlp/metrics ]
logs:
receivers: [ otlp ]
processors: [ batch ]
exporters: [ otlp/logs ]
16) Runbooks(典型脚本)
A)在"payments-api"中增长p99'
1.打开"Top slow traces" →失败到DB/PSP睡眠中。
2.如果PSP问题是转换路由,则启用retrai/taymout。
3.检查队列"withdrawals" (lag),增加消费者。
B)发布后的5xx错误
1.通过'服务过滤器。version`.
2.比较稳定/金丝雀;在'psp中找到香料。route`.
3.冻结促销活动,回滚(请参阅"发行策略"/"Rolbacks")。
C)怀疑N+1
1.具有大量短DB spans的步道。
2.启用聚合/joins,添加缓存层。
17)实施支票
1.启用OTel SDK和单一资源属性('service.name`, `env`, `region`).
2.通过所有图层和队列宣传W3C Trace Context。
3.最小语义属性集(HTTP/DB/queue/PSP)。
4.Tail-sampling: 错误,p95+,付款,绳索.
5.带有"trace_id"/"span_id"的逻辑,带有exemplars的度量。
6.Dashbords:服务地图,发行汇编,付款流量。
7.PII政策:掩护,区域,角色,重建。
8.测试/负载:在峰值之前检查相关性和完整性。
9.Alert中的runbook链接的自动生成。
10.遥测和基数成本报告。
18)反模式
没有DB/队列的"仅在入口处"跟踪→没有好处。
async中缺乏宣传→因果关系链"撕裂"。
Sampling是随机的1%,没有尾巴逻辑→不会遇到缓慢/错误。
没有"trace_id"的逻辑→没有端到端相关性。
属性/逻辑中的原始PII →合规风险。
"进入天花板"(用户/会话作为度量标签)的基数→成本爆炸。
结果
OpenTelemetry将可观察性从一组不同的工具转换为端到端性能语言。通过正确的上下文宣传,整洁的语义,尾随采样和捆绑的"轨迹度量↔ ↔ logi",iGaming团队可以控制p95/p99,快速隔离瓶颈(DB,队列,PSP),并自信地发布发行甚至在流量峰值。