K6 + JavaScript 压测服务端

发布于:2025-06-12 ⋅ 阅读:(15) ⋅ 点赞:(0)

K6是一款现代化的开源负载测试工具,专为开发和测试人员设计,可以使用JavaScript编写测试脚本。以下是完整的K6压测教程。

一、安装K6

下载地址
官网
在这里插入图片描述

二、编写第一个测试脚本

创建一个名为test.js的文件:

import http from 'k6/http';
import { check, sleep } from 'k6';

// 初始化选项
export let options = {
    vus: 10,            // 虚拟用户数
    duration: '30s',    // 测试持续时间
};

export default function () {
    // 发送HTTP GET请求
    let res = http.get('https://test-api.k6.io/public/crocodiles/');
    
    // 验证响应状态码是否为200
    check(res, {
        'is status 200': (r) => r.status === 200,
    });
    
    // 每个VU每次迭代后暂停1秒
    sleep(1);
}

三、运行测试

在终端运行:

k6 run test.js

四、进阶测试脚本

1. 带参数的POST请求

import http from 'k6/http';
import { check, sleep } from 'k6';

export let options = {
    stages: [
        { duration: '30s', target: 20 },  // 30秒内逐步增加到20个VU
        { duration: '1m', target: 20 },    // 保持20个VU1分钟
        { duration: '30s', target: 0 },    // 30秒内逐步减少到0
    ],
};

export default function () {
    // POST请求数据
    let data = JSON.stringify({
        username: 'test_user',
        password: 'test_password',
    });
    
    let params = {
        headers: {
            'Content-Type': 'application/json',
        },
    };
    
    let res = http.post('https://test-api.k6.io/auth/token/login/', data, params);
    
    check(res, {
        'login successful': (r) => r.status === 200,
        'response time < 500ms': (r) => r.timings.duration < 500,
    });
    
    sleep(1);
}

2. 使用CSV数据驱动测试

创建users.csv文件:

username,password
user1,pass1
user2,pass2
user3,pass3

测试脚本:

import http from 'k6/http';
import { check, sleep } from 'k6';
import { SharedArray } from 'k6/data';

// 读取CSV文件
const users = new SharedArray('users', function () {
    return open('./users.csv').split('\n').slice(1).map((line) => {
        const parts = line.split(',');
        return { username: parts[0], password: parts[1] };
    });
});

export let options = {
    vus: 10,
    duration: '1m',
};

export default function () {
    // 获取当前VU的用户数据
    const user = users[__VU % users.length];
    
    let data = JSON.stringify({
        username: user.username,
        password: user.password,
    });
    
    let params = {
        headers: {
            'Content-Type': 'application/json',
        },
    };
    
    let res = http.post('https://test-api.k6.io/auth/token/login/', data, params);
    
    check(res, {
        'login successful': (r) => r.status === 200,
    });
    
    sleep(1);
}

3. 测试RESTful API完整流程

import http from 'k6/http';
import { check, group, sleep } from 'k6';

export let options = {
    stages: [
        { duration: '30s', target: 20 },
        { duration: '1m', target: 50 },
        { duration: '20s', target: 0 },
    ],
    thresholds: {
        http_req_duration: ['p(95)<500'], // 95%的请求响应时间应小于500ms
        'logged in successfully': ['rate>0.9'], // 登录成功率应大于90%
    },
};

export default function () {
    // 1. 登录获取token
    group('Authentication', function () {
        let loginRes = http.post('https://test-api.k6.io/auth/token/login/', {
            username: 'test_user',
            password: 'test_password',
        });
        
        check(loginRes, {
            'logged in successfully': (resp) => resp.json('access') !== '',
        });
        
        let authHeaders = {
            headers: {
                Authorization: `Bearer ${loginRes.json('access')}`,
            },
        };
        
        // 2. 获取用户信息
        let userRes = http.get('https://test-api.k6.io/auth/users/me/', authHeaders);
        check(userRes, {
            'retrieved user info': (r) => r.status === 200,
        });
        
        // 3. 创建资源
        let createRes = http.post(
            'https://test-api.k6.io/public/crocodiles/',
            {
                name: `Croc_${__VU}_${__ITER}`,
                sex: 'M',
                date_of_birth: '2020-01-01',
            },
            authHeaders
        );
        check(createRes, {
            'created resource': (r) => r.status === 201,
        });
        
        let crocId = createRes.json('id');
        
        // 4. 获取创建的资源
        let getRes = http.get(`https://test-api.k6.io/public/crocodiles/${crocId}/`, authHeaders);
        check(getRes, {
            'retrieved created resource': (r) => r.status === 200,
        });
        
        // 5. 删除资源
        let deleteRes = http.del(`https://test-api.k6.io/public/crocodiles/${crocId}/`, null, authHeaders);
        check(deleteRes, {
            'deleted resource': (r) => r.status === 204,
        });
    });
    
    sleep(1);
}

五、结果分析与可视化

1. 输出结果到文件

k6 run --out json=result.json test.js
k6 run --out csv=result.csv test.js

2. 使用InfluxDB和Grafana可视化

  1. 安装InfluxDB和Grafana
  2. 运行测试时将结果发送到InfluxDB:
    k6 run --out influxdb=http://localhost:8086/k6 test.js
    
  3. 在Grafana中配置InfluxDB数据源
  4. 导入K6仪表板模板

3. 使用k6 Cloud

如果你使用k6 Cloud,可以直接:

k6 login cloud --token YOUR_TOKEN
k6 cloud test.js

六、高级功能

1. 自定义指标

import http from 'k6/http';
import { check, sleep, group, trend } from 'k6';

// 创建自定义趋势指标
let responseTrend = new trend('response_time');

export let options = {
    vus: 10,
    duration: '1m',
};

export default function () {
    group('API Test', function () {
        let res = http.get('https://test-api.k6.io/public/crocodiles/');
        
        // 记录响应时间到自定义指标
        responseTrend.add(res.timings.duration);
        
        check(res, {
            'is status 200': (r) => r.status === 200,
            'response time < 500ms': (r) => r.timings.duration < 500,
        });
    });
    
    sleep(1);
}

2. 使用WebSocket

import ws from 'k6/ws';
import { check, sleep } from 'k6';

export let options = {
    vus: 10,
    duration: '30s',
};

export default function () {
    let url = 'ws://echo.websocket.org';
    let response = ws.connect(url, null, function (socket) {
        socket.on('open', function open() {
            socket.send('hello');
        });
        
        socket.on('message', function (message) {
            console.log('Received: ', message);
            socket.close();
        });
        
        socket.on('close', function () {
            console.log('disconnected');
        });
    });
    
    check(response, { 'status is 101': (r) => r && r.status === 101 });
    
    sleep(1);
}

3. 分布式测试

使用k6 Operator在Kubernetes集群上运行分布式测试:

  1. 安装k6 Operator
  2. 创建测试资源文件test.yaml
    apiVersion: k6.io/v1alpha1
    kind: K6
    metadata:
      name: k6-sample-test
    spec:
      parallelism: 4
      script:
        configMap:
          name: k6-test-script
          file: test.js
    
  3. 应用配置:
    kubectl apply -f test.yaml
    

七、常见问题解决

  1. 连接被拒绝:检查目标服务是否运行,防火墙设置
  2. SSL证书问题:添加insecureSkipTLSVerify: true到请求参数
  3. 内存不足:减少VU数量或增加batch/batchPerHost参数
  4. 结果不一致:确保测试环境稳定,避免网络波动

通过以上教程,你可以使用K6和JavaScript编写全面的服务端压力测试脚本,并根据测试结果优化系统性能。