JMeter模拟并发请求

PostMan不是严格意义上的并发请求工具,实际是串行的,如果需要测试后台接口并发时程序的准确性,建议采用JMeter工具。

案例:JMeter设置20个并发卖票请求,查看后台是否存在超卖的情况

方式一:一共10张票,票余额作为成员属性放在控制器中,没做任何的锁控制

java 复制代码
package com.gingko.controller;
import com.gingko.common.GenericWebResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Random;

@RestController
@RequestMapping("ticket")
@Slf4j
public class TicketController {

    private static int TICKET_AMOUNT = 10;//一共10张票

    @PostMapping("/sell")
    public GenericWebResult sell() {
        GenericWebResult result = null;
        if(TICKET_AMOUNT > 0) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            TICKET_AMOUNT--;
            System.out.println("售票成功:余票" + TICKET_AMOUNT);
            result = GenericWebResult.ok("售票成功:余票",TICKET_AMOUNT);
        }else {
            result = GenericWebResult.error("售票失败:余票",TICKET_AMOUNT);
            System.out.println("售票失败:余票" + TICKET_AMOUNT);
        }
        return result;
    }
}

运行结果及分析:

从运行结果可以看出,在高并发的时候,出现了超卖和数据不一致的问题

方式二:一共10张票,票余额作为成员属性放在控制器中,卖票的请求方法上加锁synchronized

java 复制代码
package com.gingko.controller;
import com.gingko.common.GenericWebResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Random;

@RestController
@RequestMapping("ticket")
@Slf4j
public class TicketController {

    private static int TICKET_AMOUNT = 10;//一共10张票

    @PostMapping("/sell")
    public synchronized GenericWebResult sell() {
        GenericWebResult result = null;
        if(TICKET_AMOUNT > 0) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            TICKET_AMOUNT--;
            System.out.println("售票成功:余票" + TICKET_AMOUNT);
            result = GenericWebResult.ok("售票成功:余票",TICKET_AMOUNT);
        }else {
            result = GenericWebResult.error("售票失败:余票",TICKET_AMOUNT);
            System.out.println("售票失败:余票" + TICKET_AMOUNT);
        }
        return result;
    }
}

运行结果及分析:

从运行结果可以看出,在高并发的时候,没有出现超卖或数据不一致问题,数据结果符合预期。

方式三:TicketController对象多例,并且TICKET_AMOUNT属性不是static,每个对象各自持有

java 复制代码
package com.gingko.controller;
import com.gingko.common.GenericWebResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Random;

@RestController
@RequestMapping("ticket")
@Slf4j
@Scope("prototype") //多例
public class TicketController {

    private int TICKET_AMOUNT = 10;

    @PostMapping("/sell")
    public GenericWebResult sell() {
        GenericWebResult result = null;
        if(TICKET_AMOUNT > 0) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            TICKET_AMOUNT--;
            System.out.println("售票成功:余票" + TICKET_AMOUNT);
            result = GenericWebResult.ok("售票成功:余票",TICKET_AMOUNT);
        }else {
            result = GenericWebResult.error("售票失败:余票",TICKET_AMOUNT);
            System.out.println("售票失败:余票" + TICKET_AMOUNT);
        }
        return result;
    }
}

运行结果及分析:

从程序可以看出,20个并发请求,后台生成了20个TicketController实例,每个实例内部都持有属性TICKET_AMOUNT = 10,sell方法执行后,TICKET_AMOUNT = 9

方式一、方式二与方式三示意图区别如下:

方式一、二,堆内存中只有一个TicketController实例,并且TICKET_AMOUNT不属于实例对象,属于共享的数据区,对这种共享数据并发操作时,需要锁机制控制,防止出现数据不一致。

方式三,并发请求多少,堆内存中生成多少个TicketController实例,并且每个TicketController实例各自持有TICKET_AMOUNT,访问各自的成员属性也就不会发生数据不一致问题。

相关推荐
月明长歌7 小时前
从零构建高并发测试体系:JMeter 接口压测与全链路实战指南
jmeter
一碗面4212 天前
Jmeter的基本使用
jmeter
余防2 天前
jmeter使用
jmeter
maqiang_7202 天前
jmeter做压力测试如何找到软件瓶颈
jmeter·压力测试
少云清3 天前
【软件测试】1_性能测试实战 _商城项目介绍
jmeter·性能测试
少云清3 天前
【软件测试】8_性能测试实战 _执行测试脚本
jmeter·性能测试·测试脚本执行
卓码软件测评3 天前
【第三方高校课题软件确认测试:LoadRunner与JMeter-企业级性能测试工具选型深度对比】
测试工具·jmeter·性能优化·单元测试·测试用例
AC赳赳老秦4 天前
R语言数据分析:DeepSeek辅助生成统计建模代码与可视化图表
开发语言·人工智能·jmeter·数据挖掘·数据分析·r语言·deepseek
老友@4 天前
JMeter 在 Linux 环境下进行生产级性能压测的完整实战指南
java·linux·jmeter·性能优化·系统架构·压测·性能瓶颈