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

相关推荐
网络安全-杰克17 小时前
Jmeter压力测试工具安装与使用
自动化测试·软件测试·测试工具·jmeter·职场和发展
少云清2 天前
【金融项目实战】6_接口测试 _Jmeter自动化脚本实现(重点)
jmeter·自动化·金融项目实战
少云清3 天前
【金融项目实战】5_接口测试 _Jmeter功能脚本实现
jmeter·金融项目实战
卖个几把萌4 天前
【11】JMeter在GUI页面修改语言后右上角不显示线程数和持续时间问题解决
测试工具·jmeter
张永清-老清4 天前
每周读书与学习->JMeter性能测试脚本编写实战(四)-利用JMeter对MySQL数据库查询进行性能测试
学习·jmeter·性能调优·jmeter性能测试·性能分析·每周读书与学习
Jul1en_4 天前
【性能测试工具】JMeter下载安装、编辑环境变量和中文配置
测试工具·jmeter
一碗面4216 天前
Jmeter的进阶功能
jmeter
月明长歌8 天前
从零构建高并发测试体系:JMeter 接口压测与全链路实战指南
jmeter
一碗面4219 天前
Jmeter的基本使用
jmeter
余防9 天前
jmeter使用
jmeter