别再只画折线图:让遥测可视化直接回答容量与规模问题

2026-09-01 35 预计阅读时间: 1 分钟
来源: infoq.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

在可观测性系统里,折线图几乎是默认答案:横轴放时间,纵轴放指标,再按服务或实例拆成几条线。它适合观察趋势,却经常无法直接回答工程团队真正关心的问题:当前容量够不够?延迟由什么因素决定?需要多少台机器才能承受下一阶段的流量?

Yao Yue 在这场分享中结合长期运行大规模系统的经验,指出遥测数据不应被时间序列格式绑架。工程领导者和软件架构师需要根据问题重新组织数据,选择能够暴露容量、延迟和集群规模关系的图形。

折线图为什么经常失效

标准折线图默认了一种分析路径:先看时间,再观察变化。但很多运维问题并不是“这个指标过去几小时如何变化”,而是“不同负载下系统表现如何”。

例如,一张 CPU 使用率折线图可以告诉你某个时间点的平均 CPU,但它很难直接说明:

  • 机器数量增加后,单位实例承担的请求量是否下降;
  • 延迟开始恶化的负载拐点在哪里;
  • 少数慢实例是否拖高了整体尾延迟;
  • 当前集群规模是否足以应对下一次流量增长。

把所有数据都画成时间序列,还容易产生视觉噪声。几十条实例曲线叠在一起,读者往往只能看到颜色和波动,却无法判断数据之间的结构关系。

这并不意味着折线图没有价值。它仍然适合查看故障发生时间、发布前后变化和长期趋势。问题在于:它不应该成为所有遥测问题的默认终点。

从“指标趋势”转向“工程问题”

更有效的做法是先写出要回答的问题,再决定如何聚合和绘制数据。

容量问题:画负载与资源的关系

如果目标是估算容量,可以把请求率、并发数或吞吐量放在横轴,把 CPU、内存、队列长度或成本放在纵轴。按实例类型、区域或集群规模分组后,散点图或分位数曲线通常比时间序列更直接。

这类图形能帮助团队识别:

  • 资源消耗是否随负载近似线性增长;
  • 哪个区间开始出现排队或饱和;
  • 不同硬件规格的单位吞吐成本;
  • 扩容后性能是否真的改善。

延迟问题:展示分布,而不是只看平均值

平均延迟会隐藏尾部。对于用户体验和超时风险,p50、p95、p99 甚至完整延迟分布通常更有信息量。热力图、箱线图和按负载分桶的分位数曲线,都可以把“偶发的慢请求”从平均值中分离出来。

Fleet sizing:比较不同集群规模

当问题是“需要多少台实例”时,时间轴可能反而是干扰。可以将集群规模作为分类维度,将吞吐、延迟、错误率和资源余量放到同一组对比图中。这样更容易看到增加实例带来的收益何时开始递减。

一个可改造的遥测绘图示例

下面的 Python 示例使用一组模拟遥测数据,生成两个面向决策的视图:

  1. 请求率与 p95 延迟的关系,用于寻找延迟拐点;
  2. 不同集群规模下的吞吐与 CPU 使用率,用于辅助估算扩容效果。

示例假设 CSV 文件包含 timestampfleet_sizerequest_ratep95_latency_mscpu_utilization 字段。没有真实数据时,脚本会生成可运行的模拟数据;接入真实数据时,将 generate_data() 替换为 pd.read_csv("telemetry.csv") 即可。

from __future__ import annotations

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt


def generate_data(seed: int = 7) -> pd.DataFrame:
    rng = np.random.default_rng(seed)
    rows = []
    for fleet_size in [4, 8, 16]:
        for request_rate in np.arange(100, 1101, 100):
            capacity = fleet_size * 95
            saturation = max(request_rate - capacity, 0)
            rows.append(
                {
                    "fleet_size": fleet_size,
                    "request_rate": request_rate,
                    "p95_latency_ms": 35 + 0.015 * request_rate + 0.12 * saturation**1.25 / 10 + rng.normal(0, 3),
                    "cpu_utilization": min(99, 18 + request_rate / (fleet_size * 1.15) + rng.normal(0, 2)),
                }
            )
    return pd.DataFrame(rows)


def plot_telemetry(df: pd.DataFrame) -> None:
    fig, axes = plt.subplots(1, 2, figsize=(13, 5))

    for fleet_size, group in df.groupby("fleet_size"):
        group = group.sort_values("request_rate")
        axes[0].plot(
            group["request_rate"],
            group["p95_latency_ms"],
            marker="o",
            label=f"{fleet_size} instances",
        )
    axes[0].axhline(200, color="red", linestyle="--", label="200 ms SLO")
    axes[0].set(title="Load vs p95 latency", xlabel="Requests/sec", ylabel="p95 latency (ms)")
    axes[0].legend()
    axes[0].grid(alpha=0.25)

    summary = (
        df.groupby("fleet_size", as_index=False)
        .agg(
            peak_throughput=("request_rate", "max"),
            mean_cpu=("cpu_utilization", "mean"),
        )
        .sort_values("fleet_size")
    )
    axes[1].bar(summary["fleet_size"].astype(str), summary["peak_throughput"])
    axes[1].set(title="Fleet size vs observed throughput", xlabel="Instances", ylabel="Requests/sec")
    axes[1].grid(axis="y", alpha=0.25)

    fig.tight_layout()
    plt.show()


if __name__ == "__main__":
    telemetry = generate_data()
    plot_telemetry(telemetry)

运行方式:

python -m pip install numpy pandas matplotlib
python telemetry_views.py

在生产环境中,图表还应明确标注数据聚合方式、采样窗口、分位数定义和异常过滤规则。否则,一张外观漂亮的散点图可能只是把不同时间窗口、不同实例状态的数据混在了一起。

让图表服务于决策

遥测可视化的价值不在于图形种类更多,而在于图形是否缩短了从数据到决策的路径。一个实用的设计流程可以是:

  1. 把问题写成可验证的句子,例如“在 p95 延迟不超过 200 毫秒时,集群能承受多少请求”;
  2. 选择与问题匹配的维度,而不是自动使用时间作为横轴;
  3. 先决定聚合粒度,再决定颜色、分面和交互;
  4. 同时展示平均值与尾部、总量与单位实例值;
  5. 在图上标出 SLO、容量边界和目标集群规模;
  6. 用历史回放或压测数据验证图表是否支持真实决策。

还要注意数据之间的因果边界。相关性图可以帮助发现拐点,却不能单独证明扩容就是解决延迟的原因。实例规格、缓存命中率、请求类型和下游依赖都可能影响结果。

采用建议

保留折线图用于时间定位和变化回放,同时为关键问题补充关系图、分布图和对比图。可以从一个具体的容量评估场景开始:把请求率、p95 延迟、CPU 使用率和 fleet size 放进同一份分析数据,然后检查团队是否能直接回答“何时饱和”和“扩多少合适”。

当图表开始围绕容量、延迟和集群规模组织,而不是围绕监控系统默认的指标类型组织,遥测才真正成为架构和运营决策的一部分。


相关推荐