拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Grafana Tempo 基数(Cardinality)估算指南:从 Trace 预判 Service Graph 指标规模

Grafana Tempo 基数Cardinality估算指南从 Trace 预判 Service Graph 指标规模【免费下载链接】tempoGrafana Tempo is a high volume, minimal dependency distributed tracing backend.项目地址: https://gitcode.com/GitHub_Trending/tempo1/tempo本文是 Grafana Tempo 官方文档《Estimate cardinality from traces》的深度实战指南。当你的微服务系统规模变大、服务数量增多时metrics-generator 生成的 service graph 指标系列series数量会急剧膨胀直接影响 Prometheus 类后端的内存、存储与查询成本。本文以hop跳为核心单位给出完整的基数估算公式并结合仓库源码说明直方图桶数#hb等参数的真实取值与配置位置最后介绍如何用 dry-run 实测、如何通过 limits 在运行时管理与削减基数。读完本文你将能在开启或扩展 service graph 功能之前用几分钟估算出它可能产生的指标规模提前做好容量规划。为什么需要估算基数Cardinality基数cardinality指的是一个指标的所有标签键值对组合的总数即该指标最终会产生的唯一序列数量。因为写入时间序列数据库TSDB是按序列进行的高基数在写入端影响不大但在查询端基数越高需要遍历的项目就越多查询性能会显著下降。Tempo 的 metrics-generator 在采集 trace 的基础上会额外生成基于 Prometheus 的指标例如总 span 调用计数、span 延迟直方图、span 大小计数等。其中service graph服务图处理器通过分析 trace 中父子关系的 span 来发现边edge并用指标记录请求数与耗时从而描绘服务之间的调用关系。每一条边都对应一组client、server标签新增一个服务对就会新增一系列指标。当服务数量很多时基数就会成为一个实际问题。关键难点在于基数没有一个通用的直接公式可以精确计算因为边边由请求方向决定的数量取决于系统拓扑结构。本指南给出的是一个可操作的估算方法让你在部署前就能对指标规模心里有数。关于基数的概念性介绍可参考仓库内的 Cardinality 文档。核心概念hop跳是估算的最小单位估算的第一步是确定hops跳的数量。文档中的定义边的数量取决于系统中的节点服务数量和请求在它们之间的方向每一个 hop 就是一个唯一的客户端 服务端client server标签组合即服务图上的一条有向边。两个直观的例子一个包含 3 个节点(A, B, C)的系统其中A只调用B、B只调用C则只有2 个 hops(A → B, B → C)。同样 3 个节点(A, B, C)如果它们两两互相调用所有双向链路则有6 个 hops(A → B, B → A, B → C, C → B, A → C, C → A)。无法仅凭节点数自动算出 hops但可以确定它的上下界#services - 1 #hops #services!即最少不会少于服务数减一线性调用链最多不会超过服务数的阶乘完全互联。从源码看hop 对应 clientserver 唯一组合这一语义有直接印证在 servicegraphs.go 的onComplete方法中每个完成的边都会写入client、server标签同时处理器内部用tempo_metrics_generator_processor_service_graphs_edges计数器统计唯一边的总数其 Help 文本即为 Total number of unique edges。也就是说估算公式中的#hops本质上对应了你在 Prometheus 中看到的边数指标。估算公式从 hops 到指标系列数一旦知道了系统中的 hops 数量就可以计算 service graph 生成的各项指标基数假设#hb为直方图桶数traces_service_graph_request_total: #hops traces_service_graph_request_failed_total: #hops traces_service_graph_request_server_seconds: #hb * #hops traces_service_graph_request_client_seconds: #hb * #hops traces_service_graph_unpaired_spans_total: #services (absolute worst case) traces_service_graph_dropped_spans_total: #services (absolute worst case)各指标的含义traces_service_graph_request_total与traces_service_graph_request_failed_total是计数型指标Counter每个 hop 产生一个序列所以基数等于#hopstraces_service_graph_request_server_seconds与traces_service_graph_request_client_seconds是直方图型指标Histogram每个桶bucket都是一个独立序列因此基数要乘以桶数#hbtraces_service_graph_unpaired_spans_total与traces_service_graph_dropped_spans_total按最坏情况估算每个服务一个序列即#services。最终总的基数估算为Sum: [([2 * #hb] 2) * #hops] [2 * #services]解读每个 hop 产生 2 个直方图指标各#hb个序列加上 2 个计数器指标各 1 个序列即2 * #hb 2个序列再叠加 2 个按服务数计算的兜底指标2 * #services。默认直方图桶数#hb 的真实取值#hb是公式中最重要的乘数它的取值来自 service graph 处理器的histogram_buckets配置。源码中 config.go 的默认值如下cfg.HistogramBuckets prometheus.ExponentialBuckets(0.1, 2, 8)即采用指数桶从0.1秒开始、每次翻倍、共8 个桶实际取值为0.1, 0.2, 0.4, 0.8, 1.6, 3.2, 6.4, 12.8也就是说默认情况下#hb 8。这一点在官方 configuration 文档 的metrics_generator.processor.service_graphs一节中也有记载# Buckets for the latency histogram in seconds. [histogram_buckets: list of float | default 0.1, 0.2, 0.4, 0.8, 1.6, 3.2, 6.4, 12.8]把#hb 8代入默认场景估算公式为Sum: [(2 * 8 2) * #hops] [2 * #services] 18 * #hops 2 * #services示例一个 10 个服务、呈线性调用链的系统#hops 9#services 10估算基数约为18 * 9 20 182个序列而如果这 10 个服务完全互联#hops 10! 3,628,800估算基数将高达约18 * 3,628,800 20 ≈ 6,530 万个序列——差距惊人这正是为什么部署前必须先摸清拓扑的原因。启用消息系统延迟直方图后的公式修正service graph 处理器还支持一个可选项enable_messaging_system_latency_histogram。当它被设置为true时会额外产出一个直方图指标traces_service_graph_request_messaging_system_seconds: #hb * #hops该指标用于衡量经消息系统messaging system例如 Kafka、RabbitMQ 等中间件传递的调用所引入的中间件延迟。源码中config.go 将该选项的默认值设为false在 servicegraphs.go 的onComplete中只有当该选项开启且边的连接类型为消息系统MessagingSystem时才会记录这个直方图其值由生产者 span 结束时间与消费者 span 开始时间之差计算unixNanosDiffSec并会在两端时钟不同步时输出告警日志。开启后估算公式相应变为Sum: [([3 * #hb] 2) * #hops] [2 * #services]即每个 hop 的直方图序列从 2 组变成 3 组。代入默认#hb 8(3 * 8 2) 26也就是每个 hop 约 26 个序列。配置位置同样在 configuration 文档 的 service_graphs 一节# If enabled another histogram will be produced for interactions over messaging systems middlewares [enable_messaging_system_latency_histogram: bool | default false]需要注意的是启用该直方图后如果消息系统场景下的延迟较高涉及长时间范围官方配置文档还建议同步调大该处理器的wait值默认为10s避免边在等待配对 span 时过早过期。用 dry-run 实测验证估算估算公式是理论值实际部署前更稳妥的做法是先以 dry-run 模式运行 metrics-generator 实测。dry-run 模式会照常生成指标但不会真正写入指标存储后端因此可以安全地在生产流量的旁路观察真实基数。方法如下通过 per-tenant overrides 将metrics_generator.disable_collection设置为true然后像正常一样运行 metrics-generator查询tempo_metrics_generator_registry_active_series指标得到当前配置下活跃序列数的估算值如果活跃序列数限制已被触达、tempo_metrics_generator_registry_active_series不再反映真实需求则改用tempo_metrics_generator_registry_active_series_demand_estimate指标——它基于 HyperLogLog 估算即使在限流生效时也能近似反映真实基数。dry-run 的相关说明详见 Cardinality 文档 中的 Dry-running the metrics-generator 一节。通过 limits 管理与削减基数当估算结果超出预算、或线上已经出现基数失控时Tempo 提供了从限制到削减的多层手段运行时基数限制limits在运行时管理和排查基数问题主要依靠 metrics-generator 的三类限制Max active series最大活跃序列数检测并配置活跃序列数上限防止指标无限增长Entity-based limiting基于实体的限制按唯一的标签组合entity来限制而不是按单个序列计数粒度更贴合业务实体Per-label cardinality limiting按标签的基数限制针对单个标签限制其不同取值distinct values的数量直接约束最高基数的标签维度。这些限制既可以通过 configuration 文档 中的全局配置设定也可以通过 user-configurable overrides 文档 在运行时动态调整。从源头削减基数除了限更重要的是减。Tempo 提供了两个方向的削减手段谨慎添加自定义标签dimensionsmetrics-generator 支持把 span 属性映射为额外的标签。以span_kind、status_code这类取值有限的标签影响有限但如果你把一个取值极多的属性如唯一的客户 ID映射为标签基数可能被成倍放大——官方示例是 100 个客户 ID 可能把 25,000 个活跃序列放大到 250 万。相关背景见 Cardinality 文档。启用 span name 清洗span_name_sanitizationspan_name标签往往是高基数的主要来源例如GET /users/123、query-abc-def-ghi这类内嵌动态值的 span 名会为每个不同取值生成独立序列。启用span_name_sanitization后Tempo 使用 DRAIN 算法自动把相似 span 名归并例如把GET /users/123与GET /users/456统一映射为GET /users/_从而大幅削减序列数量。配置方法见 Reduce cardinality with span name sanitization。从估算到实战用 PromQL 验证拓扑规模完成估算后可以结合 PromQL 查询实际验证系统中的 hop 规模是否符合预期。service graph 的指标可以直接用标签聚合查询例如统计过去 7 天每一对 client/server 的总调用量sum(increase(traces_service_graph_request_server_seconds_count{}[7d])) by (server, client) 0该查询的结果行数就约等于你系统中的实际 hops 数量再配合#hb 8或你配置的桶数代入公式即可把估算值与线上实测相互印证。更多服务图查询示例含延迟分位数、消息系统延迟等见 Analyze service graph data。小结基数估算没有银弹公式但有清晰的可操作路径先通过拓扑分析确定 hops 数量上下界为#services - 1到#services!再代入Sum: [([2 * #hb] 2) * #hops] [2 * #services]开启消息系统延迟直方图时变为[([3 * #hb] 2) * #hops] [2 * #services]其中默认#hb 8。上线前用 dry-run 实测tempo_metrics_generator_registry_active_series佐证上线后用 active series 限制、实体级限制、标签级基数限制以及 span name 清洗等手段兜底。这样无论系统是 3 个服务的小集群还是数百服务的网格都能在指标规模失控之前把它算清楚、管得住。【免费下载链接】tempoGrafana Tempo is a high volume, minimal dependency distributed tracing backend.项目地址: https://gitcode.com/GitHub_Trending/tempo1/tempo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门