

用 golang 来编写压测工具
source link: https://myzhan.github.io/posts/write-a-load-testing-tool-in-golang/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

用 golang 来编写压测工具
之前在项目中做服务端性能测试,一般用的都是 LoadRunner,或者 jmeter。随着接触的项目越来越多,各种各样的代码都有,光传输协议,就有 HTTP,TCP,UDP。有时数据传的不是明文,可能是 protobuf,也可能是 RSA 加密后的密文。继续用 LR 或 jmeter,有点难以招架。
于是,我开始关注 Locust 这个压测工具。与 LR 使用的 C 和 jmeter 使用的 Java 相比,Locust 使用 Python 来编写压测代码,代码量会少很多。且 Locust 本身的概念少,学习成本较低,上手很快。
在实现并发方面,Locust 并没有使用进程、线程来实现,事实上,CPython 的实现也对多线程不友好。于是,Locust 使用 gevent 提供的非阻塞 IO,和 coroutine来实现网络层的并发请求。实际使用中,使用 Locust 编写的压测脚本,单个实例,可以提供 1000 rps 左右的压力,如果还需要更多的压力,挂多几个 slave,也能满足需求。不过我生性爱折腾,一直想着摆脱 CPython 的 GIL,和 gevent 的 monkey_patch(),过年在家无聊,就一直在构思着怎样实现一个性能更好的施压端,用golang 提供的 goroutine,应该是个不错的选择。
Locust 已经实现了 master & slave 的架构,一个 Locust 进程如果运行在 master 模式,那它要做的事情,就只是收集各个 slave 汇报上来的信息,并展示在 web界面上而已。我的想法很简单,用 golang 来实现 slave 这一部分。实现为一个框架,在运行时,按需创建 goroutine 来跑调用方提供的 function,然后定时将信息汇报给 Locust 的 master。
过年回来撸了一周,最后弄了一个 boomer ,已开源。参考 Locust 的 slave 部分代码来实现的,连文件的命名都一致,应该很容易理解。与 Locust 最大的区别,就是用 goroutine,取代了 gevent。golang 本身的性能,也是一个优势。
用 boomer 来编写一个简单的 http 压测例子。
package main
import boomer "github.com/myzhan/boomer"
import (
"time"
"net/http"
"log"
)
func now() int64 {
return time.Now().UnixNano() / int64(time.Millisecond)
}
func test_http() {
/*
一个常规的 HTTP GET 操作,实际使用时,这里放业务自身的处理过程
只要将处理结果,通过 boomer 暴露出来的函数汇报就行了
请求成功,类似 Locust 的 events.request_success.fire
boomer.Events.Publish("request_success", type, name, 处理时间, 响应耗时)
请求失败,类似 Locust 的 events.request_failure.fire
boomer.Events.Publish("request_failure", type, name, 处理时间, 错误信息)
*/
startTime := now()
resp, err := http.Get("http://localhost:8080/")
defer resp.Body.Close()
endTime := now()
log.Println(float64(endTime - startTime))
if err != nil {
boomer.Events.Publish("request_failure", "demo", "http", 0.0, err.Error())
}else {
boomer.Events.Publish("request_success", "demo", "http", float64(endTime - startTime), resp.ContentLength)
}
}
func main() {
task := &boomer.Task{
// Weight 权重,和 Locust 的 task 权重类似,在有多个 task 的时候生效
// FIXED: 之前误写为Weith
Weight: 10,
// Fn 类似于 Locust 的 task
Fn: test_http,
}
/*
通知 boomer 去执行自定义函数,支持多个
boomer.Run(task1, task2, task3)
*/
boomer.Run(task)
}
# dummy.py 可以在 boomer 代码库里找到,由于 master 不再负责实际的业务逻辑
# 所以 dummy.py 的格式,只要符合 Locust 脚本的规范就行了
locust -f dummy.py --master --master-bind-host=127.0.0.1 --master-bind-port=5557
go run main.go --master-host=127.0.0.1 --master-port=5557
boomer 目前比较完整地实现了 Locust slave 端的功能,在实际使用中,较原生的 Python 实现,有 5-10 倍以上的性能提升。
Locust 官方表示,master 和 slave 间通讯,用 zeromq 会有较大的性能提升,但是我目前并没有感觉到明显的性能差异,可能是我挂的 slave 数量还不够多吧。目前 boomer 还不支持zeromq,如果将来这里确实是个瓶颈,实现起来也很快。
Enjoy!
</div
Recommend
-
75
这两天抽空使用了一下两款压测工具 wrk Artillery 并且通过两款工具对产品的两个环境进行了测试
-
39
用 redis 的 list 数据结构作为轻量级的消息队列,对于小系统确实是小而美,可控能力强。 当然与kafka 和 rabbitmq 相比它还有很多缺陷,在服务进行生产和消费的时候,还需要加上部分逻辑进行处理。 自己写了点 golang...
-
15
golang mac m1的性能压测 – 峰云就她了
-
13
golang mac m1的性能压测 – 峰云就她了 峰云就她了 专注于Golang、Python、DB、cluster 同事在我的强烈推荐下购买了mac m1,13寸...
-
5
编写一个接口压测工具前段时间有个项目即将上线,需要对其中的核心接口进行压测;由于我们的接口是 gRPC 协议,找了一圈发现压测工具并不像 HTTP 那么多。
-
6
1. 堪比JMeter的.Net压测工具 - Crank 入门篇
-
9
上面我们已经做到了接口以及场景压测,通过控制台输出结果,我们只需要将结果收集整理下来,最后汇总到excel上,此次压测报告就可以完成了,但收集报告也挺麻烦的,交给谁呢…… 找了一圈、没找到愿意接手的人,该怎么办呢……思考了会儿还是决定看看能否通...
-
9
ab、wrk、JMeter、Locust压测工具的并发模型 发表于 2020-11-06...
-
8
Http 压测工具 -- wrk Tools | Apr 7, 2018 | Http
-
10
sysbench压测工具的使用 精选 原创 进击的CJR 2022-08-16 16:25:40
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK