证书申请流程接口性能优化 - 第3节
性能指标体系:先给系统定个调子
说实话,做性能优化最怕什么?
最怕「感觉系统慢」但说不出到底哪里慢。没有量化指标,你没法判断优化是否有效,也说服不了产品经理和老板。
我做性能优化这么多年,每次接到一个新系统,第一件事就是先把指标定下来。说白了,你得知道什么事是「正常」,什么事是「不正常」。不然出了问题,你连报警阈值该设多少都不知道。
所以这一章,咱们就聊聊性能指标这件事。我会把我在项目中常用的几个关键指标掰开揉碎了讲清楚,顺便说说怎么建一套靠谱的基准线。
QPS:系统的吞吐能力
QPS 全称是 Queries Per Second,每秒能处理多少个请求。
我习惯把它叫做系统的「上限」。你想想看,一个接口每秒只能处理 100 个请求,高峰期突然来了 300,那后面 200 个就只能排队等着,或者直接超时。
QPS 怎么测?
压测工具很多,我推荐用 wrk 或者 locust。
举个例子,用 wrk 测一个接口:
wrk -t12 -c400 -d30s http://your-api.com/v1/cert/apply
这个命令的意思:12 个线程,保持 400 个并发连接,持续压 30 秒。结果会告诉你平均 QPS 是多少,延迟是多少。
我个人习惯:压测时先做基准测试(低并发),再逐步增加并发,观察 QPS 的变化曲线。你可能会发现,并发增加到一定程度后,QPS 就不涨了,甚至开始回落——那个点就是系统的瓶颈点。
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 面板,你一眼就能看到延迟分布情况。
错误率:系统的健康指标
错误率是个很直观的指标。出错了就是出错了,没什么好说的。
但问题在于,错误率该设多少算危险?
我的经验是: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 满了——日志量太大,又没有做日志轮转。你看,资源消耗是个容易被忽略的点。
建立性能基准
有了指标,下一步就是建基线。说白了,你得知道系统在「正常」状态下该是什么样子。
我的做法是:
- 选择典型场景: 比如「无并发」、「200 并发」、「500 并发」各测一次。
- 记录完整数据: 不只是 QPS 和延迟,还包括当时系统的 CPU、内存、连接数等上下文信息。
- 固定版本: 每次大版本上线前后,都重新跑一遍基准测试,更新基线数据。
举个实际例子,我给证书申请流程定的基准线:
| 并发数 | QPS 基准 | P99 基准 | 错误率上限 | CPU 上限 |
|---|---|---|---|---|
| 100 | ≥ 800 | ≤ 50ms | 0.01% | 50% |
| 500 | ≥ 3000 | ≤ 120ms | 0.05% | 70% |
| 1000 | ≥ 5000 | ≤ 300ms | 0.1% | 80% |
有了这张表,每次上线前,只要跑一遍压测就能知道「这次优化有没有效果」「系统有没有退化」。我建议你也这么做——建个基线表格,贴在 Wiki 上,每个人都能看到。