前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >i++需要多少QPS才能测出BUG

i++需要多少QPS才能测出BUG

作者头像
FunTester
发布2022-12-09 14:03:26
4550
发布2022-12-09 14:03:26
举报
文章被收录于专栏:FunTester

前段时间我关注了一篇文章,分享如果使用并发压测发现 BUG。突然想起一个话题:

线程不安全需要多少 QPS 压测才能发现 BUG ?

我接触到的并发缺陷绝大部分是因为线程安全问题导致的,还有一些数据库锁的问题(这个不擅长)这里就不分享了。

关于 Java 的一些线程安全的问题,可以参考旧文:

下面我们来聊聊上面提到的问题,因为这涉及到不同类型的 BUG 需要多少 QPS 才能测出来 BUG,今天来分享一下最简单的线程不安全操作i++需要多少 QPS 才能测出来BUG。

用例设计思路

首先,我使用的同一个 JVM 来测试i++,发现极容易出现 BUG,后来放弃了这种方式。经过思考发现如果放在一个 JVM 里面,本身已经创建了很多线程去执行i++,这种跟实际接口测试差异比我想象的大很多。其次,我创建了一个简单的 Springboot 项目,写一个简单的接口来实现。

总提测下来,上面的问题需要修正,因为能不能测出来不是一个 Boolean 值,而是一个概率值,后面我也会用发现比例值来表示是测出 BUG 的难易程度。

服务端设计

之前一直用moco_funtester框架来构建服务端不行了,无法动态接口返回。所以只能简单弄一个 Springboot 项目。其他的就不分享了,只分享一下 controller 的部分。这里模拟盘了一个接口平均响应时间 10ms,然后执行一个非线程安全的操作。

代码语言:javascript
复制
    int i;

    @GetMapping(value = "/funtest")
    public Result test1() {
       Thread.sleep(SourceCode.getRandomInt(20));
        return Result.success(i++);
    }

    @GetMapping(value = "/geti")
    public Result test() {
        return Result.success(i);
    }
    @GetMapping(value = "/zero")
    public Result te2st() {
        i = 0;
        return Result.success(i);
    }

测试用例

这里没有使用正经的测试框架,只用了异步线程池和粗略的sleep休眠的方法控制 QPS,所以这里会有一个实际 QPS 统计。

  1. 默认以固定 QPS 执行 20s。
  2. 先重置,后执行,最后获取结果。
  3. 取消所有日志打印,避免误差
  4. 统计误差数量和误差比

测试用例模拟盘两个模型:线程模型和 QPS 模型。

线程模型用例

代码语言:javascript
复制
    public static void main(String[] args) {
        def test = {getHttpResponse(getHttpGet("http://localhost:8080/user/funtest"))}
        def get = {getHttpResponse(getHttpGet("http://localhost:8080/user/geti"))}
        def init = {getHttpResponse(getHttpGet("http://localhost:8080/user/zero"))}
        AtomicInteger index = new AtomicInteger()
        FunHttp.LOG_KEY = false
        def t = 1000
        def size = 1
        setPoolMax(500)
        init()
        fun {
            output(DEFAULT_STRING)
        }
        sleep(1.0)
        def start = Time.getTimeStamp()
        size.times {
            fun {
                t.times {
                    test()
                    index.getAndIncrement()
                }
            }
        }
        ThreadPoolUtil.waitFunIdle()
        def value = get().getIntValue("data")
        def end = Time.getTimeStamp()
        output("当前 QPS: ${index / (end - start) * 1000}")
        output(index.get(), value)
        output(getPercent(index.get(), index.get() - value))
    }

QPS 模型用例

代码语言:javascript
复制
    public static void main(String[] args) {
        def test = {getHttpResponse(getHttpGet("http://localhost:8080/user/funtest"))}
        def get = {getHttpResponse(getHttpGet("http://localhost:8080/user/geti"))}
        def init = {getHttpResponse(getHttpGet("http://localhost:8080/user/zero"))}
        AtomicInteger index = new AtomicInteger()
        FunHttp.LOG_KEY = false
        def qps = 100
        def t = qps * 10
        setPoolMax(1000)
        init()
        def decimal = 1_000_000_000 / qps
        fun {
            output(decimal)
        }
        sleep(1.0)
        def start = Time.getTimeStamp()
        t.times {
            sleepNano(decimal as long)
            fun {
                test()
                index.getAndIncrement()
            }
        }
        ThreadPoolUtil.waitFunIdle()
        def value = get().getIntValue("data")
        def end = Time.getTimeStamp()
        output("当前 QPS: ${index / (end - start) * 1000}")
        output(index.get(), value)
        output(getPercent(index.get(), index.get() - value))
    }

测试结果

线程模型

线程模型模仿的固定线程数去不断请求接口,这里由于接口平均响应时间 10ms,每个线程执行次数设计为 2000 次,差不多 20s 执行完。

设计 QPS

实际 QPS

误差数量

误差比(百分比)

10

9.6

0

0

20

18.7

0

0

50

42

0

0

100

87

2

0.1

200

174

9

0.22

300

280

18

0.3

400

285

23

0.28

500

417

2

0.02

QPS 模型

由于对实际结果测试并不能很好预期,这里就先从较小的 QPS 开始了。全程没有触发性能瓶颈,误差部分,测 5 次,取误差最大的一次记录。这里模拟的线程模型的

线程数

实际 QPS

误差数量

误差比(百分比)

1

76

0

0

2

144

1

0.05

4

305

33

0.41

8

617

111

0.69

12

927

224

0.93

经过上面测试,对于需要多少压力才能发现可能存在的缺陷,希望本文能投提供参考。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-09-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FunTester 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 用例设计思路
  • 服务端设计
  • 测试用例
    • 线程模型用例
      • QPS 模型用例
      • 测试结果
        • 线程模型
          • QPS 模型
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档