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

random 测试交流评论122字数 3000阅读模式

作者

FunTester

FunTester

FunTester,Have Fun ~ Tester !

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

线程不安全需要多少 QPS 压测才能发现 BUG ?文章源自玩技e族-https://www.playezu.com/239696.html

我接触到的并发缺陷绝大部分是因为线程安全问题导致的,还有一些数据库锁的问题(这个不擅长)这里就不分享了。文章源自玩技e族-https://www.playezu.com/239696.html

关于 Java 的一些线程安全的问题,可以参考旧文:文章源自玩技e族-https://www.playezu.com/239696.html

  • 操作的原子性与线程安全 2019-07-16
  • 快看,i++ 真的不安全 2019-07-19
  • 原子操作组合与线程安全 2019-07-22
  • 线程安全集合类中的对象是安全的么? 2020-02-24
  • Lambda 表达式在线程安全 Map 中应用 2020-06-01

下面我们来聊聊上面提到的问题,因为这涉及到不同类型的 BUG 需要多少 QPS 才能测出来 BUG,今天来分享一下最简单的线程不安全操作i++需要多少 QPS 才能测出来 BUG。文章源自玩技e族-https://www.playezu.com/239696.html

用例设计思路

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

总提测下来,上面的问题需要修正,因为能不能测出来不是一个 Boolean 值,而是一个概率值,后面我也会用发现比例值来表示是测出 BUG 的难易程度。文章源自玩技e族-https://www.playezu.com/239696.html

服务端设计

之前一直用moco_funtester框架来构建服务端不行了,无法动态接口返回。所以只能简单弄一个 Springboot 项目。其他的就不分享了,只分享一下 controller 的部分。这里模拟盘了一个接口平均响应时间 10ms,然后执行一个非线程安全的操作。文章源自玩技e族-https://www.playezu.com/239696.html

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 统计。文章源自玩技e族-https://www.playezu.com/239696.html

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

测试用例模拟盘两个模型:线程模型和 QPS 模型。文章源自玩技e族-https://www.playezu.com/239696.html

线程模型用例

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 模型用例

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 执行完。文章源自玩技e族-https://www.playezu.com/239696.html

设计 QPS实际 QPS误差数量误差比(百分比)
109.600
2018.700
504200
1008720.1
20017490.22
300280180.3
400285230.28
50041720.02

QPS 模型

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

线程数实际 QPS误差数量误差比(百分比)
17600
214410.05
4305330.41
86171110.69
129272240.93

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

  • 接口功能测试专题
  • 性能测试专题
  • Groovy 专题
  • Java、Groovy、Go、Python
  • 单测&白盒
  • FunTester 社群风采
  • 测试理论鸡汤
  • FunTester 视频专题
  • 案例分享:方案、BUG、爬虫
  • UI 自动化专题
  • 测试工具专题
玩技站长微信
添加好友自动发送入群邀请
weinxin
rainbow-shownow
玩技官方公众号
官方微信公众号
weinxin
PLAYEZU
 
  • 版权提示:本站仅供存储任何法律责任由作者承担▷诈骗举报◁▷新闻不符◁▷我要投稿◁
    风险通知:非原创文章均为网络投稿真实性无法判断,侵权联系2523030730
    免责声明:内容来自用户上传发布或新闻客户端自媒体,切勿!切勿!切勿!添加联系方式以免受骗。
  • 原创转载:https://www.playezu.com/239696.html
    转载说明: 点我前往阅读>>>
匿名

发表评论

匿名网友
确定