欢迎光临
我们一直在努力

K6+Prometheus+Grafana 监控面板配置

作为资深性能测试专家,可直接落地的 K6+Prometheus+Grafana 监控面板配置、支付系统性能测试报告模板,以及重复支付/资损等异常场景的 K6 专项测试脚本——所有内容均针对支付系统的核心风险点设计,可直接复用。


一、K6+Prometheus+Grafana 监控面板配置

1. 前置配置(Prometheus + K6 对接)

(1)Prometheus 配置文件(prometheus.yml)

global:
scrape_interval: 15s
evaluation_interval: 15s

scrape_configs:
# 采集K6指标
job_name: 'k6'
static_configs:
targets: ['k6-agent-ip:6565'] # K6压测机IP/端口

# 采集应用/数据库/Redis指标(可选,用于全链路监控)
job_name: 'pay-application'
static_configs:
targets: ['pay-api-ip:9090']
job_name: 'mysql-exporter'
static_configs:
targets: ['mysql-exporter-ip:9104']
job_name: 'redis-exporter'
static_configs:
targets: ['redis-exporter-ip:9121']

(2)K6 启动命令(对接Prometheus)

k6 run –out prometheus-remote=http://prometheus-ip:9090/api/v1/write pay_perf_test.js

2. Grafana 面板 JSON 配置(支付系统专属)

以下是适配支付系统的 Grafana 面板核心配置(可直接导入 Grafana),覆盖 K6 压测指标、应用指标、数据库/缓存指标:

{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "– Grafana –",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 1,
"links": [],
"liveNow": false,
"panels": [
{
"collapsed": false,
"datasource": null,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 0
},
"id": 2,
"panels": [],
"title": "K6 压测核心指标",
"type": "row"
},
{
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "reqs/s"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 1
},
"id": 3,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"expr": "sum(rate(k6_http_reqs[10s])) by (name)",
"interval": "",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"title": "TPS(每秒请求数)",
"type": "timeseries"
},
{
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "yellow",
"value": 500
},
{
"color": "red",
"value": 800
}
]
},
"unit": "ms"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 1
},
"id": 4,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"expr": "k6_http_req_duration{quantile=\\"0.95\\"}",
"interval": "",
"legendFormat": "P95",
"refId": "A"
},
{
"expr": "k6_http_req_duration{quantile=\\"0.99\\"}",
"interval": "",
"legendFormat": "P99",
"refId": "B"
}
],
"title": "请求耗时(P95/P99,ms)",
"type": "timeseries"
},
{
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 0.1
}
]
},
"unit": "percent"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 9
},
"id": 5,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"expr": "sum(rate(k6_http_reqs_failed[10s])) / sum(rate(k6_http_reqs[10s])) * 100",
"interval": "",
"legendFormat": "失败率",
"refId": "A"
}
],
"title": "请求失败率(%)",
"type": "timeseries"
},
{
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 5
}
]
},
"unit": "ms"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 9
},
"id": 6,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"expr": "k6_third_party_call_duration{quantile=\\"0.95\\"}",
"interval": "",
"legendFormat": "第三方调用P95",
"refId": "A"
}
],
"title": "第三方渠道调用耗时(P95,ms)",
"type": "timeseries"
},
{
"collapsed": false,
"datasource": null,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 17
},
"id": 7,
"panels": [],
"title": "数据库&缓存指标",
"type": "row"
},
{
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "yellow",
"value": 90
},
{
"color": "red",
"value": 85
}
]
},
"unit": "percent"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 18
},
"id": 8,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"expr": "(redis_keyspace_hits / (redis_keyspace_hits + redis_keyspace_misses)) * 100",
"interval": "",
"legendFormat": "缓存命中率",
"refId": "A"
}
],
"title": "Redis缓存命中率(%)",
"type": "timeseries"
},
{
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 0
}
]
},
"unit": "count"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 18
},
"id": 9,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"expr": "rate(mysql_slow_queries[10s])",
"interval": "",
"legendFormat": "慢查询数/10s",
"refId": "A"
}
],
"title": "MySQL慢查询数",
"type": "timeseries"
}
],
"refresh": "5s",
"schemaVersion": 38,
"style": "dark",
"tags": ["支付系统", "K6", "性能测试"],
"templating": {
"list": []
},
"time": {
"from": "now-1h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "支付系统性能监控面板",
"uid": "pay-perf-monitor",
"version": 1,
"weekStart": ""
}

导入方法:
  • 打开 Grafana → 左侧 Dashboards → Import;
  • 粘贴上述 JSON 内容 → 选择 Prometheus 数据源 → 点击 Import。

  • 二、支付系统性能测试报告模板(可直接填充)

    支付系统性能测试报告

    1. 测试基本信息
    项内容
    测试版本 支付系统 v2.5.0
    测试时间 2026-XX-XX ~ 2026-XX-XX
    测试环境 测试环境(配置:应用服务器4核8G×3,MySQL 8.0×1,Redis 6.0×1)
    测试工具 K6 v0.49.0、Prometheus v2.45.0、Grafana v10.2.0
    测试目的 验证支付系统核心接口性能、稳定性、异常场景韧性,定位性能瓶颈
    2. 测试范围与指标
    2.1 测试接口
    接口名称接口路径功能描述核心阈值
    创建订单 /v1/order/create 创建支付订单 P99 ≤ 200ms,成功率 ≥ 99.9%
    统一下单 /v1/pay/unifiedorder 核心支付接口 P99 ≤ 500ms,成功率 ≥ 99.9%
    支付结果查询 /v1/pay/query 查询订单支付状态 P99 ≤ 100ms,成功率 ≥ 99.9%
    支付回调 /v1/pay/notify 接收第三方回调 P99 ≤ 300ms,成功率 ≥ 99.9%
    2.2 监控指标
    指标类型监控项合格标准
    应用层 TPS、RT(P50/P95/P99)、成功率 核心接口P99≤500ms,TPS≥目标值,成功率≥99.9%
    数据库 慢查询数、锁等待时间、QPS 慢查询=0,锁等待<10ms
    缓存 命中率、内存使用率 命中率≥95%,内存使用率<80%
    第三方调用 延迟、超时率 P95≤300ms,超时率<0.1%
    服务器资源 CPU、内存、磁盘IO、网络 CPU<80%,内存<85%,无IO瓶颈
    3. 测试场景与执行结果
    3.1 基准测试
    场景并发数持续时间TPSP99耗时成功率结论
    基准测试 50 VU 5分钟 45 180ms 100% 符合预期
    3.2 容量测试
    场景并发数(阶梯)持续时间峰值TPS峰值P99耗时成功率结论
    容量测试 50→100→200→500→800 30分钟 720 450ms 99.92% 800VU时TPS达720,P99≤500ms,符合预期
    3.3 稳定性测试
    场景并发数持续时间TPSP99耗时成功率异常情况结论
    稳定性测试 500 VU 1小时 650 480ms 99.91% 无超时/报错 符合预期
    3.4 异常场景测试
    异常场景测试条件执行结果结论
    第三方渠道500ms延迟 500 VU,20分钟 P99耗时升至550ms,成功率99.85% 需优化第三方调用异步化
    缓存失效 清空Redis,500 VU 初期P99升至600ms,缓存预热后恢复至450ms 缓存预热策略需优化
    数据库慢查询(关闭索引) 200 VU,10分钟 TPS降至150,P99升至1200ms,慢查询数=15 需修复索引问题
    4. 性能瓶颈与优化建议
    瓶颈点现象描述优化建议
    第三方调用同步阻塞 第三方延迟500ms时,支付接口P99升至550ms 1. 第三方调用异步化;2. 增加熔断/降级策略
    缓存预热不及时 缓存清空后初期P99飙升 1. 压测前自动预热缓存;2. 调整缓存过期策略
    订单表索引缺失 关闭索引后TPS暴跌,慢查询增加 1. 恢复订单表idx_order_no索引;2. 巡检所有核心SQL
    5. 测试结论
  • 支付系统核心接口在800VU并发下,TPS达720,P99耗时450ms,成功率99.92%,满足性能要求;
  • 稳定性测试1小时无重大异常,系统资源使用率在合理范围;
  • 异常场景下(第三方延迟、缓存失效)系统无资损/重复支付,但第三方同步调用导致RT升高,需优化;
  • 数据库索引缺失会导致严重性能问题,需修复并建立SQL巡检机制。
  • 6. 风险提示
  • 第三方渠道超时率若超过0.1%,可能导致支付订单状态不一致,需增加重试+幂等机制;
  • 缓存命中率低于95%时,数据库压力陡增,需优化缓存Key设计;
  • 高并发下长事务可能导致锁等待,需严格控制支付事务时长。

  • 三、异常场景专项测试脚本(重复支付/资损)

    以下是针对重复支付、资损、第三方超时重试等核心风险场景的 K6 测试脚本,可直接运行:

    import http from 'k6/http';
    import { check, sleep, group } from 'k6';
    import { Trend, Rate, Counter } from 'k6/metrics';
    import { htmlReport } from "https://raw.githubusercontent.com/benc-uk/k6-reporter/main/dist/bundle.js";
    import { SharedArray } from 'k6/data';

    // 自定义指标:重复支付计数、资损风险计数
    const repeatPaymentCounter = new Counter('repeat_payment_count'); // 重复支付计数
    const fundLossRiskCounter = new Counter('fund_loss_risk_count'); // 资损风险计数
    const retrySuccessRate = new Rate('retry_success_rate'); // 重试成功率

    // 参数化数据
    const testData = new SharedArray('payment_data', function () {
    return [
    { token: 'token_001', merchant_id: 'mer_888', amount: '100.00', pay_type: 'wechat' },
    { token: 'token_002', merchant_id: 'mer_888', amount: '200.00', pay_type: 'alipay' },
    ];
    });

    // 压测配置:模拟高并发下重复请求、第三方超时
    export const options = {
    stages: [
    { duration: '5m', target: 300 }, // 300VU模拟高并发
    ],
    thresholds: {
    'repeat_payment_count': ['count<1'], // 重复支付数必须=0
    'fund_loss_risk_count': ['count<1'], // 资损风险数必须=0
    'retry_success_rate': ['rate>=0.99'], // 重试成功率≥99%
    },
    };

    // 生成唯一订单号
    function generateOrderNo() {
    return `PAY${Date.now()}${Math.floor(Math.random() * 10000)}`;
    }

    // 核心测试逻辑:重复支付、第三方超时重试、资损校验
    export default function () {
    const data = testData[Math.floor(Math.random() * testData.length)];
    const baseUrl = 'https://pay-api.test.com';
    const orderNo = generateOrderNo();
    let payResult = null;

    // 场景1:重复调用支付接口(模拟用户重复点击/网络重传)
    group('repeat_payment_test', function () {
    // 连续3次调用统一下单接口(模拟重复请求)
    for (let i = 0; i < 3; i++) {
    const params = {
    headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${data.token}`,
    },
    };
    const body = JSON.stringify({
    order_no: orderNo,
    pay_type: data.pay_type,
    client_ip: '192.168.1.100',
    });
    const res = http.post(`${baseUrl}/v1/pay/unifiedorder`, body, params);

    // 记录支付结果(首次请求)
    if (i === 0) {
    payResult = res.json();
    }

    // 检查是否重复支付:订单号相同但返回多次支付成功
    if (i > 0 && res.json().code === 0 && res.json().trade_no !== payResult.trade_no) {
    repeatPaymentCounter.add(1); // 重复支付计数+1
    }

    sleep(0.05); // 短间隔模拟重复点击
    }
    });

    // 场景2:第三方超时后重试(验证幂等性,避免资损)
    group('third_party_timeout_retry_test', function () {
    const retryParams = {
    headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${data.token}`,
    },
    };
    const retryBody = JSON.stringify({
    order_no: orderNo,
    pay_type: data.pay_type,
    client_ip: '192.168.1.100',
    // 模拟第三方超时场景
    mock_third_party_timeout: true,
    });

    // 首次调用(第三方超时)
    const firstRes = http.post(`${baseUrl}/v1/pay/unifiedorder`, retryBody, retryParams);
    const isFirstTimeout = firstRes.json().code === 500 && firstRes.json().msg === 'third_party_timeout';

    // 重试调用(验证幂等性)
    if (isFirstTimeout) {
    const retryRes = http.post(`${baseUrl}/v1/pay/unifiedorder`, retryBody, retryParams);
    const isRetrySuccess = check(retryRes, {
    '重试成功且幂等': (r) => r.json().code === 0 && r.json().order_status === 'success' && r.json().amount === data.amount,
    });
    retrySuccessRate.add(isRetrySuccess);

    // 检查是否资损:金额扣减多次
    const queryRes = http.get(`${baseUrl}/v1/pay/query?order_no=${orderNo}`, {
    headers: { 'Authorization': `Bearer ${data.token}` },
    });
    if (queryRes.json().deduct_amount > data.amount) {
    fundLossRiskCounter.add(1); // 资损风险计数+1
    }
    }

    sleep(0.2);
    });

    // 场景3:回调重复通知(模拟第三方重复回调)
    group('repeat_notify_test', function () {
    const notifyParams = {
    headers: {
    'Content-Type': 'application/json',
    'Sign': 'mock_sign', // 模拟签名
    },
    };
    const notifyBody = JSON.stringify({
    order_no: orderNo,
    trade_no: payResult?.trade_no || 'mock_trade_no',
    status: 'success',
    amount: data.amount,
    });

    // 连续2次调用回调接口(模拟第三方重复通知)
    for (let i = 0; i < 2; i++) {
    const notifyRes = http.post(`${baseUrl}/v1/pay/notify`, notifyBody, notifyParams);
    check(notifyRes, {
    '重复回调处理成功(幂等)': (r) => r.status === 200 && r.json().code === 0,
    });
    }

    sleep(0.1);
    });
    }

    // 输出测试报告
    export function handleSummary(data) {
    return {
    "./pay_abnormal_test_report.html": htmlReport(data),
    "stdout": JSON.stringify(data, null, 2),
    };
    }

    脚本核心说明:

  • 重复支付测试:连续3次调用同一订单号的支付接口,验证系统是否能防止重复扣款;
  • 第三方超时重试:模拟第三方超时后重试,验证幂等性(同一订单号仅扣减一次金额);
  • 重复回调测试:模拟第三方重复发送支付成功回调,验证系统对重复回调的幂等处理;
  • 自定义指标:repeat_payment_count(重复支付数)、fund_loss_risk_count(资损风险数),阈值设为0(不允许出现)。

  • 总结

  • 监控面板:导入提供的JSON配置,可一键生成支付系统全链路监控视图,覆盖K6压测、数据库、缓存、第三方指标;
  • 报告模板:按模板填充测试数据,可快速输出标准化的支付系统性能测试报告,重点突出核心指标和风险点;
  • 异常脚本:聚焦重复支付、资损等高风险场景,通过K6模拟真实异常场景,验证系统幂等性和容错能力,避免生产资损。
  • 赞(0)
    未经允许不得转载:171主机测评 » K6+Prometheus+Grafana 监控面板配置
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址