CC 攻击导致登录接口 RT 10 秒,如何区分是验证码逻辑还是 DB 瓶颈
解读
面试官把“登录接口 RT 暴涨”与“CC 攻击”绑定,核心想考察两点:
- 能否在高压场景下快速建立“证据链”——先证明是验证码还是数据库拖了后腿,再给出可落地的止血/优化方案;
- 是否熟悉国内常见的验证码(滑块、点选、短信、云厂商风控)链路以及 MySQL/Redis 在并发争抢时的典型症状。
回答必须体现“可观测 + 可复现 + 可量化”,避免拍脑袋式“我觉得是数据库慢了”。
知识点
- 分层监控:入口 QPS、RT 分位值、错误码分布 → 应用层(JVM/Go runtime)→ 缓存 → 数据库;
- 验证码链路:前端→验证码服务(本地 or 第三方云 API)→ 回调校验→Session/Token 写入;
- 数据库瓶颈信号:连接池打满、线程状态大量 “Waiting for table metadata lock” / “update 等待行锁”、InnoDB RW-latch 争用、慢 SQL ≥100 ms、CPU/IO 突刺;
- 验证码瓶颈信号:验证码服务 RT 高、HTTP 状态 200 但 body 返回 “verify overload”、出口带宽打满、云厂商返回 5xx/429、JVM FGCT 上涨;
- 国内压测常用工具:JMeter + 插件“自定义线程组”模拟 CC 低频长时,wrk/vegeta 做高并发短连接,Arthas 做 on-the-fly 方法耗时采样;
- 快速止血:验证码→降级为“静态图文+前端延迟”,数据库→限流 or 读写分离 or 热点账户拆行;
- SLA 量化:登录接口 P99 ≤1 s,验证码校验 ≤300 ms,数据库单 SQL P99 ≤50 ms。
答案
现场我会按“1 分钟止血、5 分钟定位、30 分钟复现”三步推进:
-
1 分钟止血
a. 打开 Grafana/阿里云 ARMS,看登录接口返回码:若 502/504 集中在验证码域名,则把验证码降级到“静态图文+前端 JS 简单算术”,观察 RT 是否瞬间掉到 1 s 内;
b. 若降级后 RT 仍 8–10 s,立即把登录接口做“影子开关”限流(Nginx+lua,令牌桶 500 QPS),保护后端,再看 RT 变化。 -
5 分钟定位
a. 对比验证码与登录两条链路的“入口→出口”耗时:- 验证码:用
curl -w "@curl-format.txt"直接压测/captcha/get,发现 TTFB 4.5 s,body 下载 5 s,基本锁定验证码; - 数据库:Arthas
trace com.xxx.dao.UserMapper.selectByMobile '#cost>100'采样 200 次,发现 P99 仅 60 ms,且连接池 activeCount 10/200,排除 DB;
b. 若反过来:验证码 TTFB 80 ms,但 MySQL 线程状态大量 “update user set last_login=now() where mobile=xxx” 等待行锁,且 InnoDB row lock waits 每秒 6 k,则锁定 DB。
- 验证码:用
-
30 分钟复现
用 JMeter 开两条线程组:- A 组直接绕过验证码(硬编码合法 token),并发 500,RT 仍 9 s,DB CPU 95%,说明问题在 DB;
- B 组只压验证码获取接口,并发 500,RT 9 s,出口带宽 95%,说明问题在验证码。
通过“单一变量”复现,给出量化报告:哪条链路耗时占比 >80%,即为主要瓶颈。
最终结论用数据说话:
“验证码服务占耗时 85%,其中云厂商滑块 API P99 7.2 s,为关键瓶颈;数据库单 SQL P99 45 ms,非主要矛盾。建议①接入备用验证码厂商并做权重灰度;②本地缓存预生成滑块底图;③异步化 last_login 更新,登录成功后发 MQ 延迟刷盘。”
拓展思考
- 如果验证码与 DB 同时到达瓶颈,如何设计“联合降级”顺序?
先降验证码(用户体验损失小),再降数据库写(延迟写),最后才降读(缓存穿透风险),保证“损失最小且可灰度回滚”。 - 国内短信验证码常遇“运营商黑洞”,如何提前探测?
在压测脚本里加入“端到端短信到达率”采样,对接云厂商回执 API,若 5 分钟内到达率 <90%,自动切换通道并报警。 - 高并发登录场景下,热点账户行锁争用可升级为“分布式限流+账户分片”,把 last_login 拆成按用户 ID 尾号分 64 张表,降低单行热度;同时用 Redis 原子滑动窗口做登录频率限制,防止 CC 变体攻击。