证书申请流程接口性能优化 - 第3节

性能指标体系:先给系统定个调子

说实话,做性能优化最怕什么?

最怕「感觉系统慢」但说不出到底哪里慢。没有量化指标,你没法判断优化是否有效,也说服不了产品经理和老板。

我做性能优化这么多年,每次接到一个新系统,第一件事就是先把指标定下来。说白了,你得知道什么事是「正常」,什么事是「不正常」。不然出了问题,你连报警阈值该设多少都不知道。

所以这一章,咱们就聊聊性能指标这件事。我会把我在项目中常用的几个关键指标掰开揉碎了讲清楚,顺便说说怎么建一套靠谱的基准线。

核心观点: 没有度量,就没有优化。你要先定义「好」的标准,才能让系统一直保持在「好」的状态。
接口性能指标体系 性能基准线 QPS 每秒查询次数 P99延迟 99%请求耗时 错误率 异常请求占比 资源消耗 CPU/内存/网络 四个指标缺一不可:QPS看容量,P99看体验,错误率看健康,资源消耗看成本。

QPS:系统的吞吐能力

QPS 全称是 Queries Per Second,每秒能处理多少个请求。

我习惯把它叫做系统的「上限」。你想想看,一个接口每秒只能处理 100 个请求,高峰期突然来了 300,那后面 200 个就只能排队等着,或者直接超时。

一个小技巧: 测量 QPS 时,记得区分「并发用户数」和「QPS」。1000 个用户同时在线,不代表系统一秒要处理 1000 个请求,因为每个用户的操作频率是不一样的。我个人习惯用「用户行为模型」来估算,比如一个用户在高峰期平均每分钟操作 2 次,那 1000 个用户的 QPS 大概就是 33 左右。

QPS 怎么测?

压测工具很多,我推荐用 wrk 或者 locust。

举个例子,用 wrk 测一个接口:

wrk -t12 -c400 -d30s http://your-api.com/v1/cert/apply

这个命令的意思:12 个线程,保持 400 个并发连接,持续压 30 秒。结果会告诉你平均 QPS 是多少,延迟是多少。

我个人习惯:压测时先做基准测试(低并发),再逐步增加并发,观察 QPS 的变化曲线。你可能会发现,并发增加到一定程度后,QPS 就不涨了,甚至开始回落——那个点就是系统的瓶颈点。

注意: 压测别在线上环境做!我曾经见过有人在生产环境跑 wrk,结果把数据库搞挂了。压测要在预发环境或者专门的压测集群上做,而且要提前跟团队打招呼。

P99延迟:用户真实体验

QPS 看的是容量,P99 看的是体验。

平均延迟其实没什么用。为什么?举个例子:100 个请求里,90 个耗时 10ms,9 个耗时 100ms,1 个耗时 10 秒。平均一下才 118ms,看起来不错对吧?但那个 10 秒的请求,用户早就骂娘了。

所以我看延迟,只看 P99。意思是 99% 的请求都落在这个时间以内。剩下的 1%,就是所谓的「尾部延迟」,你得多留意。

如何采集 P99 延迟?

如果用了 Spring Boot,可以加 Micrometer + Prometheus。代码里埋点就行了:

// 示例:Spring Boot 中记录接口耗时
@Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
public Object measureLatency(ProceedingJoinPoint pjp) throws Throwable {
    long start = System.nanoTime();
    try {
        return pjp.proceed();
    } finally {
        long duration = System.nanoTime() - start;
        // 记录到 Prometheus Histogram
        latencyHistogram.observe(duration / 1_000_000); // 转成毫秒
    }
}

Prometheus 的 Histogram 类型会帮你计算 P50、P90、P99 这些分位数。配置好 Grafana 面板,你一眼就能看到延迟分布情况。

避坑指南: 我曾经踩过一个坑——用了 P99 但没关注 P999(99.9%)。某次上线后,P99 从 50ms 涨到 80ms,我心想还行啊。结果运营反馈用户频繁报错,查了半天才发现 P999 从 200ms 飙升到了 5 秒。你看,只看 P99 差点让我漏掉大问题。

错误率:系统的健康指标

错误率是个很直观的指标。出错了就是出错了,没什么好说的。

但问题在于,错误率该设多少算危险?

我的经验是:SLA 里承诺 99.9% 可用性,那错误率就不能超过 0.1%。注意,这是对总请求量的比例。如果每天 1000 万请求,0.1% 就是 1 万个错误,这个数字其实已经不小了。

区分错误类型

错误不能一概而论。我习惯把错误分成几类:

错误类型 典型原因 处理方式
4xx 客户端错误 参数校验失败、认证过期 一般不算在可用性里,但需要监控
5xx 服务端错误 代码异常、DB 连接超时 必须计入可用性,触发告警
超时 上游接口响应慢、网络抖动 应单独统计,往往先于 5xx 出现
业务错误码 证书状态不对、余额不足 需根据业务逻辑判断是否重要

你看,光一个「错误」就有这么多门道。我个人习惯在日志里打上不同的错误标签,方便告警时快速排查。比如 error_type=5xx、error_type=timeout、error_type=invalid_param 这样。

资源消耗:别让系统跑崩了

QPS 和延迟看着挺好,不代表系统就没问题。

你想想看,如果为了达到 2000 QPS,CPU 已经跑到了 95%,内存也飙到 80%,那系统其实非常脆弱。稍微来个流量尖峰,或者别的服务抢点资源,你就挂了。

关键资源指标

我重点看这几个:

  • CPU 使用率: 别超过 70%。留点余量给突发流量。超过 80% 就得关注了。
  • 内存使用率: Java 应用注意堆内存使用情况,别一直 Full GC。
  • 网络带宽: 证书申请往往是 IO 密集型,上传下载都要占带宽。超过 50% 就危险了。
  • 磁盘 IO: 日志写入太猛也会拖慢系统。

我曾经遇到过一个案例:有个证书申请接口,QPS 一直维持在 500 左右,延迟也 OK。但过了一段时间,接口突然变慢,排查发现是磁盘 IO 满了——日志量太大,又没有做日志轮转。你看,资源消耗是个容易被忽略的点。

建立性能基准

有了指标,下一步就是建基线。说白了,你得知道系统在「正常」状态下该是什么样子。

我的做法是:

  1. 选择典型场景: 比如「无并发」、「200 并发」、「500 并发」各测一次。
  2. 记录完整数据: 不只是 QPS 和延迟,还包括当时系统的 CPU、内存、连接数等上下文信息。
  3. 固定版本: 每次大版本上线前后,都重新跑一遍基准测试,更新基线数据。

举个实际例子,我给证书申请流程定的基准线:

并发数 QPS 基准 P99 基准 错误率上限 CPU 上限
100 ≥ 800 ≤ 50ms 0.01% 50%
500 ≥ 3000 ≤ 120ms 0.05% 70%
1000 ≥ 5000 ≤ 300ms 0.1% 80%

有了这张表,每次上线前,只要跑一遍压测就能知道「这次优化有没有效果」「系统有没有退化」。我建议你也这么做——建个基线表格,贴在 Wiki 上,每个人都能看到。

小建议: 基准测试的脚本和数据要纳入版本管理。别问我为什么知道——我曾经在重构后发现压测脚本找不到了,只能凭记忆重写,结果对比数据都不准了。