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,访问各自的成员属性也就不会发生数据不一致问题。

相关推荐
叮当喵是mao2 天前
接口测试(九)jmeter——关联(JSON提取器)
jmeter·1024程序员节
幸运的星竹2 天前
jmeter自定义函数
jmeter
美团程序员2 天前
如何用Jmeter做性能测试
软件测试·jmeter
赫萝的红苹果2 天前
性能测试——Jmeter实战
jmeter
uncofish2 天前
Jmeter启动默认设置为中文
jmeter
Mr_Chenph2 天前
Jmeter实际应用
jmeter·断言·tps·jmeter插件
叮当喵是mao2 天前
接口测试(八)jmeter——参数化(CSV Data Set Config)
jmeter
uncofish3 天前
Jmeter使用js对入参使用MD5加密
开发语言·javascript·jmeter
uncofish4 天前
jmeter附件上传
jmeter
uncofish4 天前
Jmeter自动化实战
运维·jmeter·自动化