本文来自网易云社区html
做者:刘静媛
前端
前言
java
从事金融业务领域的测试工做过程已经有半年时间了,在此期间遇到了各类类型的问题,我的认为在平常测试工做中,特别是涉及资金的业务领域内,测试人员须要格外关注的方面有:系统的并发问题、幂等问题、性能问题及资损风险等。下面就是这段时间以来,在并发问题和幂等问题上站在测试角色上的一些积累和总结。数据库
1、并发问题
编程
一、什么是并发?后端
并发(Concurrency)是指系统在同一时间段内,同时执行多个计算程序。为了更好的解释并发的概念,引入并行(Parallelism)概念来进行对比分析。设计模式
下图较为形象的给出二者的工做机制:缓存
在多个线程同时工做时,单个CPU硬件环境下不可能真正同时的有多个线程在工做,此时并发机制其实是将CPU的运行时间划分红若干时间段,不一样的时间段交由不一样的线程使用,而其余线程此时属于挂起状态。在多个CPU的硬件环境下才有可能实现多个线程真正的同时工做。安全
二、并发与并行特色
服务器
并发 | 并行 |
宏观层面同时执行 | 严格的同时执行 |
解决多个不相关的任务 | 通常解决同一个任务 |
资源和数据共享 | 资源和数据隔离 |
单、多处理器都可 | 必须多处理器 |
彼此须要交互通讯 | 不须要交互通讯 |
重点是组合协调 | 重点是执行 |
三、并发的优缺点
优势:
(1)提高资源利用:这个优势是最容易理解的,多线程并发能够提高cpu的利用率,好比在一个线程等待磁盘IO资源时,CPU能够去执行另外的任务。在任务量大的状况下,并发机制可以明显减小系统耗时。
(2)模型边界清晰:可以并发的任务,应该是尽可能没有依赖关系的,是相互独立的,可以同时执行而不相互影响的。例如设计一个文件处理器,就可使用多个线程,每一个线程负责一个文件的读取和操做,在多个线程同时工做时,对每一个文件的操做是相互独立的。
(3)异步事件响应:在处理异步任务时,并发编程的优势更是显而易见的,它可以避免单线程状况下资源闲置和过分等待。创建单独的监听器,在获得异步响应时随时处理响应,高效合理的利用系统资源。
缺点:
(1)安全风险:因为同一进程下的多个线程会共享地址空间和数据,而多个线程访问资源的顺序具备不肯定性,所以在多线程并发时容易出现脏读、幻读等问题。(线程安全)
(2)活跃度风险(饥饿、死锁、活锁)
(3)性能风险:线程频繁调度切换一样会带来资源浪费。
(4)分析、编程和测试复杂
4 、并发编程常见的应用场景
定时任务、分布式任务、WS服务、Servlet、异步消息
多见于:多进程并发、集群中机器之间并发
5 、并发安全措施
数据库行级锁:悲观锁,乐观锁
全局分布式锁
应用同步和锁机制:——Synchronized\CAS;——java.util.concurrent.locks;——java.util.concurrent.atomic
使用线程安全的容器:java.util.concurrent
6 、测试角度看并发问题:
6 .1 难分析、难测试:
有些并发问题,是很难在平时测试过程当中发现的,特别是系统底层存在的并发问题,例如:
缓存更新设计不合理致使的脏数据问题——若是缓存更新的设计模式是先清除旧的缓存再更新数据库,首先这个设计是不合理的,排除设计的正确性不谈,若是在测试人员不了解缓存更新策略的状况下,执行上层业务层面的并发测试,有很大的几率是在测试过程当中并无出现问题,可是仔细分析一下,在一个外部条件触发了缓存更新的同时,有可能出现另外两个并发操做:一个更新,一个查询。在删除缓存后,有一个查询操做访问缓存没有命中,会去查数据库,并把数据库中老的数据放进缓存中,同时更新操做会更新数据库。这样致使缓存中的数据一直是老的数据,是脏数据而且会一直脏下去。而在现实测试过程当中,缓存的更新以及查询操做都发生的很是之快,很难人为造出相似或者更为复杂的并发场景。
6 .2 难定位、难复现:
你们在开发测试过程中可能都会遇到的一个场景就是在屡次执行同一个操做时,不按期的会有一个操做是执行失败了,很难找到失败的规律,测试同窗提bug时也会很难再复现出bug并保留现场给开发人员排查。甚至此类状况直接出如今了生产环境,用户反馈说操做失败,可是更难说清楚在什么状况下会失败。这种问题发生的缘由多是多种多样的,多是多线程设计的漏洞,也多是系统交互的异常状况欠考虑引发的。当遇到这种状况时,靠碰运气和屡次尝试是很笨拙的方法,关键仍是分析出可能存在的并发问题,再有针对的尝试验证,肯定是某种缘由并分析解决后,再进行并发尝试,看是否还存在问题。
6 .3 预防和发现手段:
a.业务场景分析:实际应用场景下某功能是否会出现并发状况,对于会出现并发状况,重点关心代码设计,并准备作并发测试。
b.静态代码分析:能够借助工具 Contemplate's ThreadSafe Solo,参考 http://www.contemplateltd.com/threadsafe
c.并发测试的注意事项:
(1)不放过偶发的错误和失败
(2)作好测试分析,完成非并发的功能测试后,针对测试分析时分析到的容易出并发问题的部分作独立的并发测试
(3)并发测试时,注意并发测试设置的并发线程数须要作到可调节,一般要大于CPU数量
2、幂等问题
一、幂等的概念
幂等来源于数学概念:单目运算中,x为某集合中的任意数,f为运算子,若是知足f(x)=f(f(x)),那么f运算就是幂等的。
幂等性是系统接口的一种承诺,承诺只要调用接口成功,屡次相同的输入会有相同的结果反馈和等同一次处理的影响力。声明为幂等的接口会认为外部调用失败是常态,而且失败后必然会有重试。
二、引起幂等问题的常见缘由
用户重复提交——很是容易发生,前端、后端均须要控制
网络重发——容易遗漏,但有可能发生
消息重发——容易遗漏,但有可能发生
系统间重试——须要根据业务状况来判断是否须要重试,哪些状况哪些系统须要重试
三、幂等问题的控制关键
在设计资金的系统中,幂等问题有着十分重要的地位,好比咱们定义一个接口withdraw
bool withdraw(accountId, amount)
withdraw的语义是从accountId对应的帐户中扣除amount数额的钱;若是扣除成功则返回true,帐户余额减小amount;若是扣除失败则返回false,帐户余额不变。
一种典型的状况是withdraw请求已经被服务器端正确处理,但服务器端的返回结果因为网络等缘由被丢掉了,致使客户端没法得知处理结果。若是是在交互设计或者前端展现上处理的不够好,用户会觉得此次操做执行失败,而后刷新页面或者重复提交请求,这就致使了withdraw被调用两次,帐户也被多扣了一次钱。整个过程以下图所示:
为解决此问题,须要对接口进行幂等性改造,增长一个惟一ID参数,如:
bool idempotent_withdraw(uniqId,accountId,amount)
这个ID须要全局惟一的标识一次请求,客户端的同一个业务请求只有一个uniqId,服务端在收到请求后去检查一下是否已存在这个 uniqId而且执行成功了,若是执行成功就不会再处理第二次的调用请求,如此就避免了重复扣款的问题。
整体而言,在技术实现上,控制幂等问题的关键在于惟一键+状态机。
首先,调用者在请求中携带一个惟一ID,这个ID惟一的标识一个工做单元,这个工做单元只容许被成功执行一次。
其次,接受者在收到请求,得到惟一ID时,要先去查询这个ID所标识的工做单元是否被执行过。 检查是否执行的逻辑一般是根据惟一请求ID ,在服务端查询请求是否有记录,是否有对应的响应信息,若是有,直接把响应信息查询后返回;若是没有,那么就当作新请求去处理。
四、测试角度看幂等
(1)须要更多的关注业务性质和产品设计上,是否须要作到幂等,是时间维度的幂等仍是空间维度的幂等。
(2)接口的幂等测试必定不能遗漏,因为幂等场景相对容易制造出来,幂等测试的难度远远小于并发测试,所以在作接口测试时不妨对每一个接口都思考一下是否须要幂等,须要的话就测试一下其幂等性
(3)业务场景,特别是涉及到资金流动的业务场景,对失败重试机制必定要慎重。
网易云大礼包:https://www.163yun.com/gift
本文来自网易云社区,经做者刘静媛受权发布
相关文章:
【推荐】 认识用户访谈
【推荐】 验证码什么时候能够退出历史舞台?