分析main.py模块,函数load_locustfile()通过import载入locustfile文件,返回了需要压测的locusts对象。
load_locustfile()又调用了另一函数is_locust()来过滤出压测locusts对象。该对象的核心代码包含在core.py模块。
core.py模块是locust项目的核心代码,主要由以下几部分组成:
Locust类 | 是所有模拟client类的基类。每一个Locust类实例模拟一个用户的访问行为,该行为由一系列的task任务组成。task任务包含在该类的task_set属性 |
HttpLocust类 | 继承自Locust类,用户模拟http client用户的访问行为。和Locust类的区别是,__init__()函数初始化返回了http client对象 |
TaskSetMeta元类 | 是Locust类的元类,用来给locust类提供额外的功能:定制task任务执行比例 |
TaskSet类 | task任务集,从*tasks*属性中载入task任务列表,并按照指定的sleep时间和task比例执行task |
TaskSequence类 | TaskSet类的子类,按照locust_task_order属性中定义的顺序,按序执行task |
task修饰器 | 将函数注册入task_set任务集,可以传入weight权重变量用以调整task占全部任务的执行比率 |
seq_task修饰器 | 根据传入的order参数,将被修饰的函数注册入task_set任务集,并添加额外的执行序列号locust_task_order属性 |
1,Locust()类
class Locust(object):
"""
Locust实例相当于一个压测用户,模拟用户访问被施压系统的压力。默认包含一下行为参数:施压服务器base_api,施压时间间隔,施压权重等。具体访问行为需要在task_set属性中定义。
拓展压测支持协议client,需要继承该类,然后再实现相应的协议。例如:支持http协议的扩展类HttpLocust,在Locust协议的基础上扩展支持http client
"""
host = None #施压服务器base_api
min_wait = 1000 #不同task之间的最小等待时间
max_wait = 1000 #不同task之间的最大等待时间
wait_function = lambda self: random.randint(self.min_wait,self.max_wait) #计算不同task之间的等待时间
task_set = None #TaskSet类的实例,用以定义用户的施压行为
stop_timeout = None #task任务超时时间(秒级),默认为永不超时
weight = 10 #task权重,权重越大执行概率越大
client = NoClientWarningRaiser()
_catch_exceptions = True
_setup_has_run = False # Internal state to see if we have already run
_teardown_is_set = False # Internal state to see if we have already run
_lock = gevent.lock.Semaphore() # 信号锁,确保setup仅仅被执行一次
def __init__(self):
super(Locust, self).__init__()
self._lock.acquire()
if hasattr(self, "setup") and self._setup_has_run is False:
self._set_setup_flag()
self.setup()
if hasattr(self, "teardown") and self._teardown_is_set is False:
self._set_teardown_flag()
events.quitting += self.teardown
self._lock.release()
@classmethod
def _set_setup_flag(cls):
cls._setup_has_run = True
@classmethod
def _set_teardown_flag(cls):
cls._teardown_is_set = True
def run(self, runner=None):
task_set_instance = self.task_set(self)
try:
task_set_instance.run()
except StopLocust:
pass
except (RescheduleTask, RescheduleTaskImmediately) as e:
six.reraise(Locus