下载工作台
Spring Cloud 微服务

性能压测与容量规划

试读上半部分 · 解锁后可读全文

第 17 章 · 性能压测与容量规划

本章目标:掌握微服务场景下的性能基线建立方法;使用 k6JMetersvc-spring-demo 关键链路(Gateway → BFF → order-svc)做压测;结合 ch09 Zipkin 与 ch05 熔断定位瓶颈;理解 Little 定律容量估算公式;制定 HPA 扩容指标(预习 ch19);建立压测环境隔离数据造数规范。

学时建议:6~7 小时(含 3 小时压测实验与报告)

前置spring-cloud-web ch01~ch16spring-boot-web ch17 JPA 性能概念;ch09 链路追踪;ch12 毕业项目可运行。


17.1 为什么微服务更需要压测

单体 shop-spring-demo 压测只测一个进程;svc-spring-demo 一次下单可能经过 6+ 跳:

k6 ──► Gateway ──► BFF ──► order-svc ──► Feign ──► product-svc
                              │                    └──► inventory-svc
                              └──► Stream ──► RabbitMQ
风险无压测有压测基线
Gateway 成为瓶颈上线后才发现提前调线程池/限流
Feign 雪崩下游慢拖垮上游配合 Resilience4j 阈值
DB 连接池打满502 难复现压测复现 + 调 HikariCP
MQ 积压订单延迟小时级观察 lag 与消费 TPS

原则:先单服务压测定位上限,再全链路压测验证协作;禁止直接对生产环境施压。


17.2 压测环境与数据准备

17.2.1 环境隔离

压测专用 staging(虚构域名)
├── api-staging.example.com  → Gateway
├── 独立 MySQL / Redis / RabbitMQ(勿连开发库)
└── 造数脚本 scripts/seed-loadtest.sql
要求
数据量商品 ≥1 万、用户 ≥5 千、可下单 SKU 有库存
Token预生成 100+ JWT,k6 轮询避免单用户限流
监控Zipkin + Actuator 已开(ch09)
配置与生产拓扑一致、规格可缩小

17.2.2 造数示例

-- 虚构:为 product-svc 批量插入
INSERT INTO product (name, price, stock, status)
SELECT CONCAT('load-product-', n), 99.00, 10000, 'ON_SALE'
FROM seq_1_to_10000 n;

订单写路径压测前确认 inventory-svc 库存充足,避免业务失败干扰性能数据。


17.3 压测场景设计(svc-spring-demo)

场景接口目标并发建议
S1 商品浏览GET /api/v1/products读多写少基线50~200 VU
S2 商品详情GET /api/v1/products/{id}缓存命中 vs 未命中30~100 VU
S3 下单写路径POST /api/v1/orders核心交易 TPS10~50 VU
S4 BFF 聚合GET /bff/v1/orders/{id}/detail(与 ch08 一致)多 Feign 扇出20~80 VU
S5 混合负载70% 读 + 30% 写接近真实流量按目标 QPS

SLA 参考(教学虚构,按业务调整)

指标目标
P95 延迟读 < 300ms,写 < 800ms
错误率< 0.1%(非 429 限流)
下单 TPSstaging 单集群 ≥ 50(记录基线)

17.4 k6 脚本示例

安装 k6 后,在 svc-spring-demo/scripts/load/ 创建:

// order-create.js — 虚构 api-staging.example.com
import http from 'k6/http';
import { check, sleep } from 'k6';
import { SharedArray } from 'k6/data';

const tokens = new SharedArray('tokens', function () {
  return JSON.parse(open('./tokens.json')); // 预生成 JWT 数组
});

export const options = {
  scenarios: {
    ramp_order: {
      executor: 'ramping-vus',
      startVUs: 0,
      stages: [
        { duration: '2m', target: 20 },
        { duration: '5m', target: 20 },
        { duration: '2m', target: 0 },
      ],
    },
  },
  thresholds: {
    http_req_failed: ['rate<0.01'],
    http_req_duration: ['p(95)<800'],
  },
};

export default function () {
  const token = tokens[__VU % tokens.length];
  const headers = {
    Authorization: `Bearer ${token}`,
    'Content-Type': 'application/json',
    'X-Tenant-Id': 'tenant-demo',
  };
  const payload = JSON.stringify({
    items: [{ productId: 1001, quantity: 1 }],
  });
  const res = http.post(
    'https://api-staging.example.com/api/v1/orders',
    payload,
    { headers }
  );
  check(res, { 'status 2xx': (r) => r.status >= 200 && r.status < 300 });
  sleep(1);
}

运行:

k6 run scripts/load/order-create.js
k6 run --out json=results.json scripts/load/order-create.js

JMeter 等价:线程组 + HTTP 取样器 + CSV 数据源(JWT);GUI 调试后 CLI -n -t plan.jmx 无界面跑。


17.5 指标解读与瓶颈定位

压测时同步观察:

以下内容需解锁后阅读

试读已结束。解锁本章 ¥5.00,或开通年度会员畅读全部教程。
年度会员 ¥199.00/年; 小紫 AI 工作台有效会员 ¥99.00/年

正文仅在服务端鉴权后下发,未付费无法获取下半部分内容。