1、功能都对,一上线就垮

团队内部测试一切正常,功能没问题。上线当天搞了个活动,流量一冲——页面转圈、接口超时、数据库连接池打满,全线雪崩。

另一个更隐蔽的故事:功能稳定跑了一年,某天被安全研究者发现用户列表接口能把别人的数据全拉出来(越权),数据泄露上了新闻。

功能测试只能证明"做对了",证明不了"扛得住"和"守得住"。 本课补上这两块:性能测试与安全测试。

2、性能测试:问四个问题

性能不只是"快不快",要分场景问:

类型问题目的
负载测试(Load)在预期负载下表现如何?验证能不能扛住日常/峰值
压力测试(Stress)超过极限会怎样?找崩溃点、看是否优雅降级
并发测试同时操作会不会出错?查竞态、超卖、死锁
浸泡测试(Soak)长时间运行会退化吗?查内存泄漏、连接泄漏

核心指标:

QPS / RPS     每秒请求数(吞吐)
响应时间 P95  95% 的请求在这个时间内返回(比"平均值"更有意义)
错误率        请求失败的比例
资源占用      CPU / 内存 / 连接数 / 磁盘 IO
为什么看 P95 而不是平均? 平均 50ms 听着很好,但可能 5% 的用户等了 5 秒——长尾体验才是用户真正感受到的。

3、怎么测性能

# 用 locust 写一个压测脚本
from locust import HttpUser, task

class TaskClient(HttpUser):
    @task
    def list_tasks(self):
        self.client.get("/api/tasks")

    @task(3)                        # 权重 3:更频繁地调用
    def create_task(self):
        self.client.post("/api/tasks", json={"title": "load-test"})

工具箱:

  • k6 / JMeter / Locust / wrk:压测工具。
  • 压测要有基线:先测"当前版本",改动后再测,对比才有意义。
  • 压测要找瓶颈:逐步加压,观察哪个资源先到顶(CPU?DB?连接池?),那才是瓶颈。

性能优化常见手段:加缓存、数据库加索引、连接池调优、异步化、水平扩容、限流降级。

但要记住:先测量,再优化。凭感觉优化是浪费——先看 Profiler 和指标,找到真正的热点。

4、安全测试:常见攻击面

漏洞原理防护
SQL 注入用户输入拼进 SQL,改变语义参数化查询(占位符),永不拼字符串
XSS注入恶意脚本,在别人浏览器执行输出转义、CSP、HttpOnly Cookie
越权(IDOR)改个 id 就能看别人数据服务端鉴权:每次校验"这数据属于你吗"
CSRF借你的登录态发请求CSRF Token、SameSite Cookie
敏感信息泄露密码明文、日志带 token哈希存储、脱敏、最小暴露
依赖漏洞用的库有已知 CVE依赖扫描、定期升级

SQL 注入对比:

# ❌ 危险:字符串拼接
sql = f"SELECT * FROM users WHERE name='{name}'"
# 输入 name = "' OR '1'='1" → 拉出所有用户

# ✅ 安全:参数化查询
cursor.execute("SELECT * FROM users WHERE name = %s", (name,))

越权的经典案例:

# ❌ 只校验"登录了",没校验"是不是你的"
@app.get("/api/orders/{order_id}")
def get_order(order_id):
    return db.query(Order, id=order_id)

# ✅ 服务端强制校验归属
@app.get("/api/orders/{order_id}")
def get_order(order_id, current_user=Depends(auth)):
    order = db.query(Order, id=order_id, user_id=current_user.id)
    if not order:
        raise HTTPException(404)     # 别用 403 泄露"它存在但不属于你"
    return order

核心心法:永远不信任客户端。前端校验只是体验,真正的鉴权与校验必须在服务端。

5、安全测试的方法

方法说明
静态扫描(SAST)扫源码找危险模式(如拼接 SQL)
依赖扫描(SCA)扫第三方库的已知漏洞(如 pip-audit、npm audit、Dependabot)
动态扫描(DAST)对运行中的系统跑扫描器(如 OWASP ZAP)
渗透测试人主动模拟攻击,找逻辑漏洞
代码审查安全清单式 Review(输入校验、鉴权、日志脱敏)

OWASP Top 10:安全领域的"必知清单",列出最常见的十类 Web 漏洞(注入、鉴权失效、敏感数据泄露……),值得每人过一遍。

把安全左移:别等上线前才扫描。把依赖扫描和 SAST 塞进 CI(第 15 课),让漏洞在提交时就暴露。

6、非功能需求的验收

性能和安全的坑在于:它们通常不是"功能",容易被漏掉。解法是在需求阶段就写成可验收的非功能需求(第 7 课):

性能需求(可测):
  - 首页 P95 响应 < 800ms(100 并发下)
  - 订单接口 QPS ≥ 500
  - 内存占用稳定(8 小时浸泡无增长)

安全需求(可测):
  - 所有输入参数做类型与长度校验
  - 所有资源接口做归属鉴权
  - 依赖无 HIGH/CRITICAL 级别已知漏洞
  - 密码用 bcrypt/argon2 加盐哈希存储

能写成数字的需求,才能被自动验证。

7、常见误区

误区问题正解
上线后才做性能测试架构问题来不及改关键路径尽早压测(左移)
只看平均值掩盖长尾慢请求看 P95 / P99
盲目优化猜错瓶颈白费力先测量(Profiler/指标)再动手
只靠前端校验绕过前端即失守服务端必须重新校验
一次扫完就完事新漏洞/新依赖不断出现扫描进 CI,持续进行
用 403 暴露资源存在泄露信息给攻击者用 404 统一处理

8、动手实验 🎯

任务:给贯穿项目「团队任务清单」做一次性能 + 安全体检。

  1. 写压测脚本(Locust 或 k6):压 /api/tasks 列表接口,逐步加到 200 并发。
  2. 记录基线:测出 QPS、P95 响应时间、错误率,画一张"并发 vs 延迟"曲线。
  3. 找瓶颈:加压时观察哪个资源先到顶(CPU/DB/连接池),写下你的判断依据。
  4. 优化一处:针对瓶颈做一项优化(如加索引/缓存),再测一次对比,证明有效。
  5. 安全自查:在你的项目里找/修三类问题——SQL 注入、越权、敏感信息日志。
  6. 接扫描:在 CI 里加依赖扫描(pip-audit 或 Dependabot),制造一个"含已知漏洞的旧依赖",看它是否报红。
  7. 反思:性能和安全的测试,为什么越早做越便宜?

下一阶段进入交付与运维——从第 24 课「构建与打包」开始。

9、今天你带走的三句话

  1. 性能看 P95 而非平均;先测量、找到瓶颈,再优化。
  2. 永远不信任客户端:参数化查询防注入、服务端做归属鉴权。
  3. 性能与安全要写成可测的非功能需求,并左移进 CI。

下一阶段:交付与运维。

标签: 软件工程, 项目管理, 开发流程

添加新评论