会员身份类的case在执行过程中会有身份状态变化、校验等情况,如果使用同一个测试账号并行的去执行这类case则会导致执行失败,那么如何去解决这个问题呢?
最简单的方法:case分组
不同组case使用不同的账号,每组case串行执行,这样就能串行执行n组case了。但随之而来的就是管理case的成本,case越多,成本越大。纯靠规则来约束case,也难免会遇到新人操作case造成的执行错误。
高阶方案:账号池
实现一个账号池,每个case执行之前先从账号池中取出一个账号,执行完成后,调用账号池接口进行回收(或等待x秒后由账号池自动回收),以此来达到任何case都可并行执行,并发n倍的目的。
代码Demo:
import flask
from flask import Flask
import redis
from flask_apscheduler import APScheduler
# 可用池,每次接口获取账号都从可用池中随机捞取一个
ValidPool = 'xpool:valid'
# 不可用池,又worker自动进行回收重置账号身份
InvalidPool = 'xpool:invalid'
# 账号锁,case占用时对账号进行标记
LockKey = 'xpool:lock_{xid}'
class Config(object):
JOBS = [
{
'id': 'job',
'func': 'scheduler:reset_worker',
'trigger': 'interval',
'seconds': 5
}
]
SCHEDULER_API_ENABLED = True
app = Flask(__name__)
app.config.from_object(Config())
scheduler = APScheduler()
scheduler.init_app(app)
scheduler.start()
redis = redis.Redis(host='127.0.0.1', port=6379)
@app.route('/api/get', methods=['GET'])
def get():
args = flask.request.args.to_dict()
duration = int(args.get('duration', 30))
# 从可用池中获取账号
xid = redis.spop(ValidPool)
if not xid:
return {'status': 1, 'msg': 'get nothing in pool'}, 200
lock = LockKey.format(xid=xid)
# 锁住账号
redis.setex(name=lock, time=duration, value='1')
# 将账号推到不可用池
redis.sadd(InvalidPool, xid)
return {'status': 0, 'xid': xid}, 200
def reset(xid):
# 回收重置逻辑
print('reset xid: {}'.format(xid))
return
def reset_worker():
xid_list = redis.smembers(InvalidPool)
if not xid_list:
return
for xid in xid_list:
lock = LockKey.format(xid=xid)
# 判断是否仍被锁住
if redis.get(lock):
continue
# 重置账号
reset(xid)
# 从不可用池中移除
redis.srem(InvalidPool, xid)
# 推到可用池中
redis.sadd(ValidPool, xid)
return
if __name__ == '__main__':
app.run(port=8666)