Tempo服务端必须暴露gRPC和HTTP双端点,需显式配置memberlist或Consul支持水平扩展,默认仅监听localhost:3200,gRPC端口4317必须显式启用,否则OTLP Trace静默丢弃;Go客户端须用OTLP exporter而非Jaeger,采样应由服务端统一控制,存储后端推荐S3+DynamoDB或GCS+Bigtable。

Tempo服务端部署必须暴露gRPC和HTTP双端点
Tempo不是开箱即用的“接入即生效”组件,服务端必须显式配置 memberlist 或 consul 后端来支持水平扩展,否则单节点无法承载大规模Trace写入。默认只监听 http://localhost:3200,但Golang微服务上报Trace时走的是gRPC(tempo:4317),若未启用gRPC接收器,所有OTLP Trace会被静默丢弃——你不会看到错误日志,只会发现Jaeger UI里完全没数据。
关键配置项必须包含:
-
server.http_listen_port设为 3200(供UI和健康检查) -
server.grpc_listen_port显式设为 4317(否则gRPC server不启动) -
metrics_generator.enabled关闭(它会额外打爆Prometheus指标采集链路) -
storage.trace.write_batch_size调大到1000(小批量写入在高吞吐下导致大量小对象GC压力)
Go服务中用OpenTelemetry SDK对接Tempo要绕过Jaeger Exporter
很多团队习惯用 go.opentelemetry.io/otel/exporters/jaeger,但它只支持Thrift协议,而Tempo 2.0+已废弃Thrift接收器;强行配 jaeger-collector:14250 会返回 rpc error: code = Unimplemented desc = 。必须切换到OTLP exporter,且版本需匹配:Tempo 2.2+要求OTLP v1.0.0+,对应SDK至少用 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0+。
初始化示例(省略context和error处理):
立即学习“go语言免费学习笔记(深入)”;
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
exp, _ := otlptracegrpc.New(context.Background(),
otlptracegrpc.WithEndpoint("tempo:4317"),
otlptracegrpc.WithInsecure(), // 内网可关TLS
)
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exp),
sdktrace.WithResource(resource.MustNewSchemaVersion(1, 0).WithAttributes(
semconv.ServiceNameKey.String("user-service"),
)),
)注意:WithInsecure() 不是开发专属——Tempo默认不带mTLS,生产环境应配 WithTLSCredentials() 并挂载CA证书,否则K8s Pod间通信失败。
Trace采样率必须在服务端统一控制,客户端不能各自为政
Golang服务里如果调 sdktrace.WithSampler(trace.AlwaysSample),等于把全量Span塞进网络,瞬时流量可能击穿Tempo gRPC连接队列。Tempo本身支持动态采样策略,应通过 tempo.yaml 的 overrides.configs 段统一管理:
overrides:
configs:
- tenant_name: default
sampler:
type: probabilistic
param: 0.01 # 1%采样
此时Go客户端只需用 trace.NeverSample 或默认采样器,让Tempo网关层做最终决策。否则多个服务不同采样率会导致Trace断裂——比如A服务采样10%,B服务采样1%,跨服务调用的Span大概率只有一半出现在Tempo里。
大规模场景下Trace ID索引性能取决于后端存储选型
Tempo支持 local、gcs、s3、azure 四种后端,但local模式根本不能用于生产:它把Trace按ID哈希分片存本地磁盘,扩容时无法迁移分片,查询会超时。实际选型只有两个可行路径:
- S3 + DynamoDB(AWS环境):DynamoDB存索引,S3存原始Trace块,查Trace ID延迟稳定在
200ms内 - GCS + Bigtable(GCP环境):Bigtable提供毫秒级索引查询,但冷热分离需手动配置TTL,否则存储成本指数增长
别信文档里“S3兼容存储都行”的说法——MinIO虽能跑通,但ListObjects性能差,Trace搜索响应常卡在 5s+,根本没法用。

















