.. _chapter2:

====================================
第 2 章 度量的基本概念与方法论
====================================

.. admonition:: 本章你将学到

   - 微服务的局限性以及度量为什么是必要条件
   - 度量的三个维度：度量工作、度量产品、度量用户
   - 度量的层次：从基础设施到业务，再到 AI 质量
   - 度量类型：Counter、Gauge、Histogram、Summary 的选择指南
   - 度量策略：USED 框架、RED 方法、黄金信号的适用场景


开篇故事
========

   *我们的 API 服务 P99 延迟从 200ms 飙到了 5 秒，但均值只有 300ms。
   运维同事看了一眼监控面板说："平均延迟 300ms，一切正常啊。"*

   *问题是，我们的面板只展示了均值。P99 = 5s 意味着每 100 个请求中有 1 个
   要等 5 秒以上——如果你的系统每秒处理 1000 个请求，
   那就是每秒有 10 个用户在忍受 5 秒的等待。*

   *从那以后，我们的所有延迟指标都改用了百分位数。*

这个故事告诉我们：**选错了度量指标，比没有度量更危险——
因为它会给你一种"一切正常"的虚假安全感。**

本章系统地介绍度量的基本概念和方法论，帮助你选对指标、用对方法。


微服务有很多优点，但缺点也很明显。本章简要介绍微服务的一些局限，
并揭示度量为什么对微服务如此重要，然后系统全面地从术语、内容、层次、方法选择等角度
剖析度量是什么以及如何做。


2.1 微服务的局限
================

2.1.1 局限
----------

微服务不是灵丹妙药，有一利必有一弊。

同样的事情，交给一个人做（单体服务）与交给一群人（多个微服务）做，差别巨大:

- 一个人做的好处是无沟通协调成本，出了问题只需找一个人
- 一群人做可以群策群力，齐头并进，但沟通协作成本直线上升

微服务的主要局限:

- 不断增长的微服务数量会导致 **信息屏障**
- 必须应对分布式系统固有的各种故障（网络延迟、抖动、丢包等）
- 问题的发现与诊断更加困难，需要多个团队共同协作
- **数据一致性** 难以保证
- **服务编排** 的复杂性
- **分布式事务** 的处理

2.1.2 解决方案
--------------

针对微服务的局限，可以从以下方面来改善:

**1. 化繁为简**

各司其职，简化对外接口和彼此的交互，把复杂性隐藏封装在内部。

**2. 快速迭代**

"天下武功，唯快不破":

- 快速演变
- 快速伸缩
- 快速上线

**3. 自动化**

- 自动化集成：构建部署流水线 (CI/CD)
- 自动化测试：单元测试、API 测试、消费者契约测试
- 自动化运维：度量驱动运维，日常操作全部自动化

**4. 容错设计**

- **分流**: 负载均衡，将流量合理分派给健康的节点
- **限流**: 根据设定的阈值，限制请求速率
- **断流**: 断路器模式，智能断开或恢复与下游的连接

**5. 度量**

及时发现问题、修复问题并避免类似问题。度量让你"见微知著"，
不放过任何一个产品线上的问题。


2.2 度量的重要性
================

   *"Own your codes on production"* -- 掌控你在产品线上的代码

作为软件工程师，不能仅仅交付产品给运维人员就完事了。
你必须深刻了解你的代码在产品线上是怎么运行的，是否和你想的一样。

度量就是你了解产品线运行情况的 **眼睛**:

- **没有度量 = 盲人摸象**: 你不知道系统的真实状态
- **有了度量 = 了如指掌**: 你可以看到系统的全貌

度量驱动开发 (MDD) 的核心理念:

.. code-block:: text

   Plan → Do → Check → Act (PDCA)
     ↑                      │
     └──────────────────────┘

- **Plan**: 制定度量计划，确定关键指标
- **Do**: 实现度量代码，收集度量数据
- **Check**: 分析度量数据，发现问题和趋势
- **Act**: 基于度量结果采取行动，持续改进


2.3 度量内容
============

2.3.1 按度量的目标划分
----------------------

**1. 度量工作 (Measure Your Work)**

- **工作量**: 代码行数、提交次数、Sprint 完成率
- **进度**: 里程碑达成率、迭代速率
- **效率**: 构建时间、部署频率、变更前置时间
- **质量**: 代码覆盖率、缺陷密度、代码审查通过率

.. tip::

   推荐使用 DORA 四个关键指标来度量团队的交付效能:

   1. **部署频率**: 组织多久部署一次代码到生产环境
   2. **变更前置时间**: 从代码提交到代码在生产环境中成功运行所需时间
   3. **变更失败率**: 部署导致生产环境故障的百分比
   4. **服务恢复时间**: 从生产环境故障中恢复需要多长时间

**2. 度量产品 (Measure Your Production)**

- **健康度**: 服务可用性、错误率、响应时间
- **使用量**: QPS、并发连接数、活跃用户数
- **趋势**: 负载变化趋势、资源消耗趋势
- **KPI**: 业务关键绩效指标

**3. 度量用户 (Measure User Behavior)**

- **DAU/MAU**: 日活跃/月活跃用户数
- **用户旅程**: 用户在系统中的行为路径
- **功能使用率**: 各功能模块的使用频率
- **满意度**: NPS (净推荐值)、APDEX (应用性能指数)

2.3.2 按度量的层次划分
----------------------

.. list-table:: 微服务度量层次
   :header-rows: 1
   :widths: 20 30 50

   * - 层次
     - 关注点
     - 典型指标
   * - 基础设施层
     - 硬件和操作系统
     - CPU、内存、磁盘、网络
   * - 中间件层
     - 数据库、缓存、消息队列
     - 连接池、命中率、队列深度
   * - 应用程序层
     - 服务性能和健康
     - TPS、响应时间、错误率
   * - 业务层
     - 业务目标和用户体验
     - DAU、转化率、收入

**基础设施层指标**

.. code-block:: text

   ┌──────────────────────────────────────────────┐
   │              System Metrics                   │
   ├──────────┬──────────┬──────────┬──────────────┤
   │   CPU    │  Memory  │   Disk   │   Network    │
   │ ──────── │ ──────── │ ──────── │ ──────────── │
   │ usage%   │ used/free│ IOPS     │ bandwidth    │
   │ load avg │ swap     │ latency  │ packet loss  │
   │ iowait   │ cache    │ capacity │ connections  │
   └──────────┴──────────┴──────────┴──────────────┘

- **处理器 (CPU)**: 使用率、负载均值、上下文切换、中断
- **内存 (Memory)**: 使用量、剩余量、交换区使用、缓存命中
- **磁盘 (Disk)**: IOPS、读写延迟、容量使用率
- **网络 (Network)**: 带宽利用率、丢包率、TCP 连接数

**应用程序层指标**

- **TPS (每秒事务数)**: 系统每秒处理的事务量
- **响应时间**: P50、P90、P95、P99 延迟
- **成功率**: 请求成功比例
- **总次数**: 总请求/事务计数

**业务层指标**

业务层指标因业务而异，但有几个通用指标:

- **用户满意度 (APDEX)**: 基于响应时间的用户满意度评分
- **转化率**: 用户完成目标行为的比例
- **留存率**: 用户在一段时间后继续使用的比例

2.3.3 AI 应用度量层次（新增）
------------------------------

随着 LLM、RAG、AI Agent 的普及，度量层次需要扩展:

.. list-table:: AI 应用度量层次
   :header-rows: 1
   :widths: 20 30 50

   * - 层次
     - 关注点
     - 典型指标
   * - 基础设施层
     - GPU、向量数据库、模型服务
     - GPU 利用率、VRAM、向量索引大小
   * - 模型服务层
     - LLM 推理性能
     - TTFT、TPS、Token 使用量、推理延迟
   * - 应用逻辑层
     - RAG 检索、Agent 编排
     - 检索精度、工具调用准确率、步骤数
   * - 质量层
     - AI 输出质量
     - 忠实度、相关性、幻觉率、准确率
   * - 成本层
     - API 调用成本
     - $/query、$/task、Token 成本
   * - 业务层
     - 用户价值
     - 任务完成率、用户满意度、ROI

与传统度量层次的关键区别:

- **质量层是 AI 特有的**: 传统 API 返回 200 就是成功，LLM 返回 200 但答案可能是错的
- **成本层更加重要**: LLM 按 Token 计费，成本与输入长度直接相关，需要精确追踪
- **确定性 vs 概率性**: 传统系统是确定性的，AI 系统是概率性的，需要统计性评估

.. tip::

   AI 应用的度量遵循一个原则: **越往上越重要，越往下越容易量化**。
   基础设施层的 GPU 利用率很容易测量，但业务层的"用户是否满意"很难量化。
   好的度量体系需要从上到下全覆盖。详见第 9 章。


2.4 度量指标与术语
==================

2.4.1 统计学指标
----------------

- **均值 (Mean/Average)**: 所有样本值的算术平均
- **中位数 (Median)**: 将样本排序后的中间值
- **百分位数 (Percentile)**: P50、P90、P95、P99 等
- **标准差 (Standard Deviation)**: 数据的离散程度
- **方差 (Variance)**: 标准差的平方

.. warning::

   在度量延迟时，**不要使用均值**，而应该使用百分位数。
   均值会掩盖长尾延迟问题。例如，P99 = 5s 意味着 1% 的请求延迟超过 5 秒，
   这可能影响大量用户，但均值可能只有 200ms。

2.4.2 度量类型
--------------

常见的度量类型:

.. list-table:: 度量类型
   :header-rows: 1
   :widths: 20 30 50

   * - 类型
     - 说明
     - 示例
   * - Gauge (测量值)
     - 某个瞬时值，可增可减
     - 当前 CPU 使用率、活跃连接数
   * - Counter (计数器)
     - 单调递增的累计值
     - 总请求数、总错误数
   * - Meter (速率)
     - 事件在一段时间内的平均速率
     - 每秒请求数、每分钟错误数
   * - Histogram (直方图)
     - 数据流的统计分布
     - 响应时间分布、请求大小分布
   * - Timer (计时器)
     - 持续时间的直方图 + 调用次数的速率
     - API 调用耗时

2.4.3 度量处理相关术语
----------------------

- **采样 (Sampling)**: 定期获取度量数据的快照
- **聚合 (Aggregation)**: 将多个数据点合并为一个（求和、平均等）
- **降采样 (Downsampling)**: 降低数据精度以节省存储
- **时间窗口 (Time Window)**: 数据聚合的时间范围
- **标签/维度 (Tag/Dimension)**: 度量数据的分类维度
- **基数 (Cardinality)**: 标签值的种类数量


2.5 度量策略选择
================

2.5.1 如何做度量
----------------

度量的基本步骤:

1. **确定度量目标**: 你想知道什么？要验证什么假设？
2. **选择关键指标**: 不要贪多，聚焦于最重要的指标
3. **设计采集方案**: 在哪里埋点？用什么工具？
4. **实现度量代码**: 编写代码收集度量数据
5. **聚合与存储**: 将度量数据聚合、存储到时序数据库
6. **展示与分析**: 用仪表盘展示，用查询分析
7. **报警与响应**: 设置阈值，自动报警
8. **持续优化**: 基于度量结果不断改进

.. code-block:: text

   确定目标 → 选择指标 → 设计方案 → 实现采集
       ↑                                  │
       │                                  ▼
   持续优化 ← 报警响应 ← 展示分析 ← 聚合存储

2.5.2 如何选择度量方案
----------------------

选择度量方案时需要考虑:

- **数据量**: 预估每秒产生的度量数据量
- **延迟要求**: 需要实时还是准实时？
- **存储周期**: 度量数据需要保留多长时间？
- **查询模式**: 主要的查询场景是什么？
- **成本预算**: 基础设施和运维成本
- **团队技能**: 团队对哪些技术栈更熟悉

常见的技术栈选择:

.. list-table:: 度量技术栈对比
   :header-rows: 1
   :widths: 20 30 25 25

   * - 技术栈
     - 特点
     - 适用场景
     - 代表工具
   * - TIG
     - 轻量、灵活
     - 中小规模系统指标
     - Telegraf + InfluxDB + Grafana
   * - ELKK
     - 全文搜索、日志分析
     - 日志聚合分析
     - Elasticsearch + Logstash + Kibana + Kafka
   * - Prometheus
     - Pull 模型、告警集成
     - 云原生环境
     - Prometheus + Grafana + Alertmanager
   * - OpenTelemetry
     - 统一标准、厂商中立
     - 全栈可观测性
     - OTel Collector + 后端存储


.. admonition:: 🔬 动手实验：15 分钟添加 4 种度量
   :class: tip

   **目标**：用 Prometheus 客户端库为一个 Hello World 服务添加 Counter、Gauge、Histogram、Summary 四种度量。

   **步骤**：

   1. 创建一个简单的 HTTP 服务 (Python Flask 或 Go Gin)
   2. 添加 ``http_requests_total`` (Counter)
   3. 添加 ``http_connections_active`` (Gauge)
   4. 添加 ``http_request_duration_seconds`` (Histogram)
   5. 添加 ``http_request_size_bytes`` (Summary)
   6. 访问 ``/metrics`` 端点，观察指标格式

   **完整代码**：见 GitHub 仓库 ``examples/ch2-four-metrics/``


2.6 本章小结
============

.. note::

   **关键要点：**

   - 度量是微服务成功的必要条件——没有度量就是盲人摸象
   - 度量分为基础设施、中间件、应用、业务四个层次，AI 应用还需要质量层和成本层
   - **使用百分位数而非均值来度量延迟**——均值会掩盖长尾问题
   - USED（Usage, Saturation, Error, Delay）是核心度量维度
   - 度量驱动开发遵循 PDCA 循环：Plan → Do → Check → Act


.. admonition:: 📝 思考题

   1. 你的系统目前使用均值还是百分位数来度量延迟？如果是均值，P99 可能是多少？
   2. 用 USED 框架分析你最熟悉的一个服务，四个维度分别应该度量什么？
   3. Counter 和 Gauge 的区别是什么？在什么场景下容易选错？
