runners.py模块是控制locust运行的核心功能,控制着性能测试的运行机制。包含了本地运行,分布式运行等。
主要由LocustRunner,LocalLocustRunner,DistributedLocustRunner,MasterLocustRunner以及SlaveLocustRunner三个类组成。其中LocustRunner类是其他类的基类,MasterLocustRunner和SlaveLocustRunner是DistributedLocustRunner的拓展类。
LocustRunner
LocustRunner是其余所有runner类的基类,也是整个locust中运行的核心代码
class LocustRunner(object):
# 实例化LocustRunner时,需要传入两个参数:locust_classes和options
def __init__(self, locust_classes, options):
self.options = options # 命令行中传入的参数
self.locust_classes = locust_classes # locust类,task任务列表
self.hatch_rate = options.hatch_rate # 命令行参数:每秒启动数
self.num_clients = options.num_clients # 命令行参数:并发数
self.host = options.host # 命令行参数:被压服务器地址
self.locusts = Group() #协程组:gevent.pool.Group()
self.greenlet = self.locusts
self.state = STATE_INIT # 压测状态,初始状态为“READY”
self.hatching_greenlet = None
self.exceptions = {}
self.stats = global_stats # 在stats模块中,有一个全局变量global_stats用于存储当前状态
# 注册监听器,当收到reset_stats指令时重置当前性能数据stats状态
def on_hatch_complete(user_count):
self.state = STATE_RUNNING
if self.options.reset_stats:
logger.info("Resetting stats\n")
self.stats.reset_all()
events.hatch_complete += on_hatch_complete
# 属性request_stats:返回当前性能指标状态
@property
def request_stats(self):
return self.stats.entries
# 属性errors:返回当前错误信息
@property
def errors(self):
return self.stats.errors
# 属性user_count,返回用户并发数
@property
def user_count(self):
return len(self.locusts)
def weight_locusts(self, amount, stop_timeout = None):
"""
根据权重分发各个Locust类占有的并发数量bucket,amount为总并发数
"""
bucket = []
# 计算权重之和
weight_sum = sum((locust.weight for locust in self.locust_classes if locust.task_set))
for locust in self.locust_classes:
if not locust.task_set:
warnings.warn("Notice: Found Locust class (%s) got no task_set. Skipping..." % locust.__name__)
continue
if self.host is not None:
locust.host = self.host
if stop_timeout is not None:
locust.stop_timeout = stop_timeout
# 根据每个locust请求的权重计算所占的比例
percent = locust.weight / float(weight_sum)
# 计算出每个locust请求需要多少个并发数
num_locusts = int(round(amount * percent))
bucket.extend([locust for x in xrange(0, num_locusts)])
return bucket
def spawn_locusts(self, spawn_count=None, stop_timeout=None, wait=False):
"""
执行压力测试并发任务
spawn_count: 并发数
stop_timeout:超时时间
wait: task任务执行间隔
"""
# 如果没有传入spawn_count参数则使用命令行传入的并发数
if spawn_count is None:
spawn_count = self.num_clients
#获取任务并发数
bucket = self.weight_locusts(spawn_count, stop_timeout)
spawn_count = len(bucket)
#如果是首次启动/重启性能测试,并发数等于传入的spawn_count
if self.state == STATE_INIT or self.state == STATE_STOPPED:
self.state = STATE_HATCHING
self.num_clients = spawn_count
else: #如果当前性能测试已经启动,则叠加spawn_count并发数
self.num_clients += spawn_count
logger.info("Hatching and swarming %i clients at the rate %g clients/s..." % (spawn_count, self.hatch_rate))
#获取每一个task任务
occurence_count = dict([(l.__name__, 0) for l in self.locust_classes])
def hatch():
sleep_time = 1.0 / self.hatch_rate #用户并发间隔,为每秒新增请求数的倒数
while True:
if not bucket:
# 当bucket为空时,表示增压已经完成