用例结果统计遇到的并发问题

脚本任务执行时,用例单个结果回传会出现并发问题,导致数据覆盖。解决方案是将测试结果统计方法设为同步方法,借助redis自增方法统计用例数。但使用@Transactional和synchronized时存在线程安全问题,需将同步方法放在事务之上。

1、问题背景

脚本任务下关联了一批用例,脚本任务执行会把用例发送到执行器执行。执行器执行任务,并将其中的每个用例执行结果通过http请求回传到研测平台。数据平台对测试结果进行统计,计算已经执行了多少用例,成功多少,失败多少,并在任务执行完成后,发送运行结果通知给对应的执行人。由于用例是单个结果回传,就会出现如下图显示的并发问题:两个运行结果相同的用例几乎同时到达研测中心,各自从数据库读取任务执行日志,然后passCount(记录成功用例数),failCount(记录失败用例数)自增,然后入库测试任务日志的方式,就存在结果覆盖的问题,导致数据不对。

2、解决方案

对于并发问题,很容易就能想到可以通过“同步”方式解决。

解决方法:

1、测试结果统计的方法加上synchronized修饰,将方法变成同步方法。在进入synchronized修饰的方法时,需要获取对象锁。

2、在任务执行时,将任务总的用例数totalCaseCount存入redis中,key为taskLogId。并借助redis的自增方法incr,设置failCountKey统计失败用例数,passCountKey统计成功用例数,初始值为0。

3、在结果回传统计方法中,如果用例失败,则failCountKey自增1,如果用例成功,则passCountKey自增1。然后校验成功用例+失败用例数是否等于任务总的用例数。如果相等,说明任务执行完成。

期间还是遇到了偶现的并发问题。后经排查,发现@Transactional 和synchronized一起使用存在线程安全问题,如下图。同步方法被事务包围,当其中的同步方法执行完成后,锁就被释放,其他线程就可以进入同步方法。但在此期间,可能事务还未提交,导致读取的数据事务提交前的。

【解决方法】:将同步方法放在事务之上。

 /**
     * 用例结果回传
     *
     * @param result
     */
    public synchronized void caseRunResultCallBack(PyCaseRunResultDTO result) {
        // 校验参数
        checkCallBackParams(result);
        setCaseRunLog(result);
    }

    
     @Transactional(rollbackFor = Exception.class)
    public void setTestCaseRunLog(PyCaseRunResultDTO result) {
    // 统计用例执行结果
    }

具体可以参考博客:

https://zhuanlan.zhihu.com/p/56961571

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值