专栏首页用户7731250的专栏压测工具locust特性以及实现
原创

压测工具locust特性以及实现

1. 背景

目前接触以及听说过的压测工具/框架繁多,如jmeter/k6/locust/loadrunner/qload等,每个压测工具都有自己特性和不足,如何选择适合自己的压测工具,简单高效的完成自己的压测目标,是我们应该思考的问题,本文旨在对locust的特性以及实现进行梳理,方便并对qload以及jmeter进行一个简单的横向对比。

locust工具地址:https://github.com/locustio/locust/

locust官方文档:https://locust.io/

2. 特性

  1. 基于python,requests,zeromq(分布式),coroutine(高并发)的开源(支持二次开发)压测工具;
  2. 压力实现方式为模拟用户操作+gevent实现并发;
  3. 设计简单优雅,模块间耦合低,为使用者的二次开发拓展提供极大的便利;
  4. 支持多场景多协议压测,如restapi/redis/mysql等等,原生支持对http协议的压测;
  5. 支持定制化结果展示,locust默认使用flask后台上报到原生的web前端,可定制使用es+kibana/prometheus+grafana等;
  6. 支持多平台,locust-master+boomer-salve的分布式方式提高并发。

3. 使用

支持单机/分布式执行压测,由于python 受限于GIL,导致locust高并发下一言难尽,想要发挥单机性能可选用单机主从的分布式方式执行压测,若还不能满足压力要求可进一步增加执行机节点,采用一主错从的方式,甚至可拓展使用boomer来进一步发挥执行机性能。

脚本编写:

脚本locustfile.py

3.1单机

locust -f locustfile.py

3.2 单机主从

locust -f locustfile.py --master

locust -f locustfile.py --woker

3.3 多机主从

locust -f locustfile.py --master

locust -f locustfile.py --woker --master-host=192.168.x.xx

4. 实现

实现与qload较为相似,都采用了模拟用户操作+gevent+节点结果采集上报的方式实现生产压力和结果收集。

4.1 架构

locust与qload架构图如下:

qload&&locust架构图
  • qload与locust架构相似,qload借助QTA的分布式能力,将任务下发到执行机,locust采用master-salve的方式,借助zeroMQ,在压测准备阶段,指定节点的角色;
  • master与slave之间使用pyzmq(zeromq的python实现)建立一对多的连接;
  • 通过节点采集器通过flask上报到前端,原生的结果展示较为简单且无法保存,往往我需要自己定制结果展示;

4.2 依赖

依赖
  • gevent:python协程库,给locust提供并发能力;
  • requests:发送http请求,locust重新封装;
  • flask:web框架,给locust的压测页面提供后台服务;
  • pyzmq+msgpack:做分布式的消息通信。

4.3 模块

从核心代码中看locust原生实现

核心类

4.3.1 用例模块

类似qload,通过vu来定义各种协议以及动作权重等。

  • User:压测所需要的“用户”,用户的行为由其属性以及方法定义,这个类通常由真正客户端需要的用户类来继承,如HttpUser,实现了支持http协议的客户端用户;
  • HttpUser:压测所需要可产生http请求的“用户”,继承于User类,这个类在实例时会创建一个client,用于在请求之间保持用户会话;
  • HttpSession:为HttpUser的实例提供client,继承于requests.Session,用于执行http请求和在请求之间保存状态,并且使用上下文管理器的方式定制返回的结果,每个请求都会被记录,用于locust的结果展示;
  • TaskSet:定义“任务”组,被“用户”所执行,且TaskSet可以嵌套(支持套娃),可以分配权重,执行时间由定义“用户”的User类的wait_time属性决定。

4.3.2 控制模块

locust/runners.py
  • Runner:通过启停和编排“用户”来进行压测,是DistributedRunner的基类;
  • DistributedRunner:和Runner基本一样,但是进行了一系列事件监听的注册,用于测试结果的上报,监听在3.3.5事件钩子中会分析;
  • MasterRunner:master节点的Runner核心,本身不会产生任何greenlets,但会与WokerRunner进行连接,控制启停greenlets,并将WokerRunner产生的压力结果进行聚合;
  • WokerRunner:salve节点的Runner核心,会与MasterRunner进行连接,被master控制的启停“用户”greenlets,并定期将“用户”生成的数据统计,并上报至WokerRunner。

Runner中的state属性记录节点的状态,master与slave共有7种状态

locust/runners.py:28

Runner的状态虽然不多,但实现了master和salve之间的状态同步,控制了压测的启停,注:下图中hatching在最新的locust版本中,由spaning代替

执行状态
  • ready:准备就绪,master和salve启动后默认状态;
  • spawning:正在准备压力机,master通知salve准备启动压测,salve过渡到running的一个状态;
  • running:执行压测;
  • cleanup:执行stopping前的一个状态;
  • stopping:正在通知各个salve停止压测;
  • stopped:压测已停止;
  • missing:状态丢失,master3s没有收到salve就会默认为missing;

4.3.3 通信模块

提供m-s之间的通信能力,封装了zeromq

locust/rpc
  • BaseSocket:socket基类,封装了zeromq,提供了1:N特性,每个master与salve之间各维持一个tcp连接,提供master命令下发和salve信息上报能力;
  • Server:继承BaseSocket,作为压测系统的Server端;
  • Clint:继承BaseSocket,作为压测系统的Client端;
  • Message:消息的封装,序列化与反序列化,数据是通过WorkerRunner的stats_report上报;

master和salve之间通信的消息类型,共10种,salve发送至master的8种,master发送至slave的3种:

locust/runners.py:626
locust/runners.py:771
  • spawn:只有master发送,开始执行;
  • stop:只有master发送,点击停止;
  • quit:退出包括异常退出;
  • client_ready:salve启动后和压测停止;
  • client_stopped:压测完成并发停止后;
  • heartbeat:心跳,3s一次;
  • stats:压测信息,3s一次;
  • spawning:用户准备过程中;
  • spawning_complete:用户数据集分配等完成;
  • exception:user执行过程中出现error;

4.3.4 统计模块

结果采集/分析,定义数据上报格式等,在master和slave通信中的stats的消息类型,作用是salve给master发送的消息,默认3s上报一次,stats中的数据从哪里来?又存储在什么样的对象中?发送给master后,进行怎样的聚合?

locust.stats
  • RequestStats:该类保存请求统计信息 locust/stats.py:187
    • 在每一个locust实例中(无论是master还是salve),RequestStats都是单例,包含了单个salve汇总的信息,以及各个请求url或或name的统计信息,在分布式下,每一个salve都会维护一个RequestStats实例,3s周期通过stats_reporter方法将信息发送到master,上报的方式在DistributedRunner实例时通过调用setup_distributed_stats_event_listeners方法,用事件钩子方式进行注册监听,发送完后salve runner的stats会调用reset_all方法进行重置;
    • self.total :StatsEntry实例,记录成功率,失败率等等,对于master来说,每3s的周期就会调用extend方法进行累加,周期的调用方法也是通过setup_distributed_stats_event_listeners方法;
    • self.entities:字典,key为(name, method),value为StatsEntry实例;
    • self.errors:字典,key为name+method+error封装的哈希值,value为StatsError实例;
  • StatsEntry:表示单个统计项(名称和方法) locust/stats.py:614
    • 实际上报的数据如下:
locust.stats.StatsEntry.serialize

StatsError:统计错误信息 locust/stats.py:671

- 实际上报的数据如下:
locust.stats.StatsError.to_dict

4.3.5 事件钩子

locust/event.py
  • EventHook:给locust不同类型的事件提供钩子
locust/event.py

Events:事件集合

- 原生支持11种事件
locust/event.py

钩子实现原理

定义处理函数 --> add_lisener注册到eventhook --> 触发执行eventhook -->hook的fire 遍历执行处理函数

  • 定义处理函数并注册:
locust/stats.py:692
  • 触发执行eventhook:
locust/runners.py:812
  • hook遍历并执行处理函数:
locust/event.py:33

钩子的使用方式,原生eg:

1. 常规方式

locust.stats.setup_distributed_stats_event_listeners

2. 使用装饰器

examples.extend_web_ui.extend.on_request_success

5. 对比

便捷度:jemter > qload > locust

工具栈:jemter > locust/qload

并发能力:locust(boomer) > qload > jemter

可拓展性:locust > qload > jemter

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 压测工具locust特性及实现

    目前接触以及听说过的压测工具/框架繁多,如jmeter/k6/locust/loadrunner/qload等,每个压测工具都有自己特性和不足,如何选择适合自己...

    kaynli
  • 开源性能压测工具 locust

    在定位系统瓶颈时,考虑被测系统 cpu,网络,磁盘,缓存和数据库情况,同时也要关注测试机器的情况。

    orientlu
  • 性能测试工具locust源码分析

    目前接触以及听说过的压测工具/框架繁多,如jmeter/k6/locust/loadrunner/qload等,每个压测工具都有自己特性和不足,如何选择适合自己...

    历久尝新
  • Locust性能评测及优化详解

    在《性能测试工具Locust源码浅析》中,我们进行了一个主流程的分析。本次我们将对Locust进行实际的评测,在具体的评测之前,为了评测结果尽量的准确,我们需要...

    上帝De助手
  • 性能专题:Locust工具实战之开篇哲学三问

    在上一篇性能专题的文章:性能专题:性能测试实施全过程指南,已提前剧透告知了,从本篇开始,将结合服务端性能测试的两款常用工具进行实战操作介绍:Jmeter和Loc...

    测试开发技术
  • 软件性能:Locust工具实战之开篇哲学三问

    在上一篇性能专题的文章:性能专题:性能测试实施全过程指南,已提前剧透告知了,从本篇开始,将结合服务端性能测试的两款常用工具进行实战操作介绍:Jmeter和Loc...

    测试开发技术
  • Locust + Boomer 基于 K8S 分布式压测使用说明

    Locust 是近几年新兴的开源测试压力项目,主要是基于 Python 的多进程和协程的方式来实现并发压力。

    charrli
  • 软件性能测试方案-性能测试工具选型

    在往期文章《软件性能测试方案-性能测试准备》介绍了前期性能测试准备的要点,本文主要介绍性能测试工具的选型。

    用户5521279
  • 基于web界面的locust性能测试

    做为一个压测工具(库),[locust](http://locust.io/) 其实解决这么一个问题:AB 之类压测工具不能编写复杂的因果逻辑,而现实场...

    用户6367961
  • 测试开发:你所需要掌握了解的性能测试知识

    大多数测试人员在谈到性能测试时,往往会倍感压力。对于我来说更是如此,想做好性能测试需要庞大的知识体系,不断实践所总结的经验教训更是弥足珍贵。而且每个人对性能测试...

    测试开发技术
  • Locust 介绍

    那么有这么多的测试工具为啥要选择 Locust呢? 还记得前面介绍过的 HttpRunner吗?

    Criss@陈磊
  • Python技术栈性能测试工具Locust入门

    Locust是一款Python技术栈的开源的性能测试工具。Locust直译为蝗虫,寓意着它能产生蝗虫般成千上万的并发用户:

    dongfanger
  • 测试开发:新手学习性能测试经验分享,值得收藏!

    大多数测试人员在谈到性能测试时,往往会倍感压力。对于我来说更是如此,想做好性能测试需要庞大的知识体系,不断实践所总结的经验教训更是弥足珍贵。而且每个人对性能测试...

    测试开发技术
  • 性能测试框架对比初探

    最近收到一项任务,就是对比主流开源性能测试框架,我搜了一些,列出来JMeter、k6、Gatling、siege、ngrinder、locust以及FunTes...

    FunTester
  • http压测工具推荐和体验报告

    功能测试用python、shell之类的脚本,勉强可以胜任。性能压力测试再手动写脚本,就有点力不从心了。

    用户1311276
  • 性能测试

    随着5G时代的到来,以及万物互联时代的到来,云应用和云服务会越来越多,数据量会指数级增长。尤其是2020年全球疫情的时代意义,会导致各行各业开始上云。从而会催生...

    派大星在吗
  • 蝗虫过境,你的系统能扛住吗?

    将Locust与常用的LoadRunner和Jmeter进行对比,详细参数如下:

    用户5521279
  • 如何选择一个性能测试工具(LoadRunner和Locust的一次对比)

    LoadRunner,是一种预测系统行为和性能的负载测试工具。通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题,LoadRunner能够对整...

    Criss@陈磊
  • Locust压测框架入门

    Locust是一个容易使用、分布式的压力测试工具。它是用于网站压力测试(或其它系统)并找出多少用户一个系统可以承载。

    我被狗咬了

扫码关注云+社区

领取腾讯云代金券