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

相关推荐
网络安全指导员5 小时前
如何在JMeter中配置断言,将非200状态码视为测试成功
网络·学习·jmeter·安全·web安全·架构
侧耳倾听1115 小时前
性能测试之jmeter的基本使用
jmeter
WIN赢6 小时前
Jmeter的压测使用
jmeter
海姐软件测试2 天前
Postman参数化设置如何设置?
开发语言·jmeter
lifewange2 天前
Jmeter面试题
jmeter
一棵树长得超出它自己2 天前
jmeter if控制器在loop控制器执行结束后执行
前端·jmeter
zzhz9253 天前
Jmeter(性能指标、指标插件、测试问题、面试题、讲解稿)
java·jvm·jmeter
熙客3 天前
Jmeter-负载测试
jmeter·压力测试
ylatin3 天前
jmeter web压力测试 压测
jmeter·压力测试
zzhz9254 天前
Jmeter操作(数据库)
数据库·jmeter