第3章 高并发场景定义:QPS、连接数、响应时延指标

咱们做PKI SDK优化的,第一步得搞清楚对手是谁。

高并发。

这个词听着玄乎,其实就三个数:QPS、连接数、响应时延。三个指标定了,场景就定了。场景定了,优化才有方向。

3.1 QPS——每秒能干多少活

QPS(Queries Per Second),每秒查询数。说白了,就是你的SDK一秒钟能处理多少次签名、验签、证书申请、CRL下载。

我见过不少团队上来就喊“我们要支持10万并发”。结果一问,他们把QPS和连接数混在一起。这是两码事。

一个典型PKI场景的QPS构成:

  • 证书签署请求:涉及到私钥生成、签名运算、数据库写入
  • 证书验证请求:证书链校验、CRL/OCSP查询、签名验证
  • CRL下载请求:返回文件或流,IO密集型
  • 状态查询:轻量级,但量大

举个例子。我在一个项目中做过测试:一台8核机器,裸跑RSA 2048签名。不加任何优化,QPS大概在2000左右。但加上证书链验证、日志输出、数据库交互,QPS直接掉到300。

为什么?因为瓶颈转移了。CPU不再是瓶颈,IO才是。

3.2 连接数——别让TCP成为筛子

连接数,指的是客户端与SDK服务端之间的TCP连接数量。高并发场景里,连接数往往比QPS更先暴露问题。

我个人习惯把连接数分成两类:

类型 说明 典型场景
短连接 请求来一次,建一次连接。处理完就断开。 证书验证、CRL下载
长连接 连接建立后保持复用。多个请求走同一条连接。 签名服务、数据订阅

我曾经踩过一个坑:

短连接模式下,QPS到了5000,服务器直接报“Too many open files”。以为是内存不够,查了半天才发现TCP TIME_WAIT状态堆了4万个。操作系统默认的本地端口范围只有3万左右。端口用光了,新连接建不了。

解决办法?要么调大端口范围,要么切长连接。

你想想看,一个PKI SDK如果同时要维持10万个证书的OCSP查询,每个查询都来一次三次握手。光握手开销就能吃掉70%的CPU。

3.3 响应时延——用户等得起吗

响应时延,从客户端发出请求到收到完整响应的时间。单位是毫秒。

PKI场景下,这个指标很敏感。证书签署慢了,用户觉得卡。OCSP查询慢了,浏览器直接报错。

我一般把时延分成三段:

  1. 网络时延:客户端到服务器的往返时间。这个SDK控制不了,但可以用连接池、CDN缓存绕过去。
  2. 排队时延:请求到了服务器,但线程池满了,在队列里等着。这个最容易被忽略。
  3. 处理时延:实际干活花的时间。签名运算、数据库查询、证书链解析。

一个经验数据:

PKI SDK的典型目标:P99时延控制在200ms以内。超过500ms,用户就能感觉到“卡”。超过1秒,用户就开始骂了。

3.4 三个指标的关系

我把它们画了个图,你看看就清楚了。

高并发核心指标关系图 高并发场景核心指标关系图 QPS 每秒查询数 连接数 并发连接 响应时延 毫秒 决定 影响 体现 系统容量天花板 三者共同决定:峰值 QPS × 时延约束 × 连接资源 指标单独优化不可取 需要三者平衡 高并发 = 高QPS + 低时延 在有限连接下实现 监控三者变化趋势 定位真实瓶颈 优化目标:在限制连接数内,压榨单连接吞吐,降低处理时延

看到没?三个指标相互拉扯。

  • 连接数开得多,QPS理论上能上去。但上下文切换变多,时延会涨。
  • 时延压得太低,可能就得牺牲连接复用,QPS反而上不去。
  • QPS追求极致,连接数和时延必然有个会爆。

所以做PKI SDK优化,不是死的。你得先知道当前系统卡在哪一维,然后对症下药。

3.5 一个实战:定义你的高并发场景

光说概念太虚。我给你一个我在项目中用过的定义模板。

// 高并发场景定义模板(Java伪代码)
public class HighConcurrencyScenario {
    private int targetQPS;         // 目标QPS,比如 10000
    private int maxConnections;    // 最大连接数,比如 2048
    private long p99LatencyMs;     // P99响应时延,比如 200ms

    // 场景类型
    public enum ScenarioType {
        CERT_SIGN,      // 证书签署:CPU密集+IO密集
        CERT_VALIDATE,  // 证书验证:CPU密集
        CRL_DOWNLOAD,   // CRL下载:IO密集
        OCSP_QUERY      // OCSP查询:轻量但高频
    }

    // 约束条件
    public boolean isFeasible() {
        // 判断当前系统能否达标
        // 如果连接数不够,提示扩容或改长连接
        // 如果时延超标,提示加缓存或异步处理
    }
}

我个人习惯用这个模板跟客户对齐需求:

先问:你峰值QPS是多少?再问:你允许的最慢响应是多久?最后问:你打算开多少连接进来?

三个数字敲死,优化就有方向了。

3.6 避坑指南:别被平均值骗了

很多项目汇报时说“平均响应时延50ms”。听着挺好。但你看P99,可能已经2秒了。

这就是为什么我反复强调:高并发场景必须看尾延迟。

PKI SDK里,最怕的就是个别大证书链验证把线程池占住,其他请求都排队。平均时延看着还行,但5%的请求已经超时了。

我曾经吃过这个亏:

一个金融客户的证书链最长有8级,每次验签要下载4张CA证书。平时1000QPS扛得住,但一旦遇到这种长链请求,5张并发就把线程池打穿了。P99从120ms飙升到3.2秒。

后来我加了两个措施:一是证书结果缓存;二是把长链验证切到异步线程池隔离。才把P99拉回到250ms以内。

所以,定义高并发场景时,别忘了加上P99指标。光看平均值,那是给自己挖坑。

3.7 小结:三个数字,一张图

做PKI SDK优化,先回答三个问题:

  1. QPS目标是多少?——决定了你的并行处理能力
  2. 连接数上限是多少?——决定了你的资源消耗
  3. P99响应时延是多少?——决定了用户体验底线

三个数字定下来,优化才是有的放矢。否则就是在黑箱里乱调。

嗯,这一章就到这。记住这三个指标,后面几章我们才能聊具体怎么优化。