当开发http 接口的时候,每每咱们会关心开发的server能承受多少压力,这时候一个比较经常使用的工具是 apache bench。一部分状况下ab工具确实能知足需求,可是不少时候并不能,须要分布式式测试工具。python
压力测试比较关心的是产生压力
、获取测试对象的如TPS、响应时延等性能数据
和主机资源如cpu,memory消耗数据
以定位性能瓶颈,简单的单机测试工具并不能很好的知足这些需求。nginx
咱们能够选择云平台的分布式测试工具,好比腾讯的wetest,阿里云也有相似产品。可是这种产品每每收费不菲。也能够选择相似的开源产品,好比locust。可是调研发现,这种开源产品每每比较简单,或者过于陈旧。google官网有一个压力测试例子,用的就是locust。你们能够看一下这个工具,基于python,功能很是简陋,master,slave模式,不支持在线编辑脚本,修改测试要重启。git
k8s是目前比较流行的容器编排系统,是否能够在k8s上本身作一个分布式测试工具呢。固然能够用google推荐的作法,在k8s上运行master slave 模式的locust,又或者本身动手作一个。
既然运行在k8s上,那么这个测试工具实际上关心的事就比较简单了:k8s已经实现了调度,资源监控,咱们的工具只须要定义脚本,运行脚本,统计测试结果,收集测试过程的资源消耗。
须要说明的是,测试工具运行在k8s上只是为了利用k8s的基础设施,简化工具设计,事实上测试的对象能够是运行在k8s上或者在k8s外的任何服务。github
选择golang做为测试脚本的缘由一是语言成熟,语法简单,二是goroutine很方便,很容易把压力打上去,三是即有编译型语言的高性能,同时又像脚本同样可以快速运行(编译很快)。golang
golang自己是编译型语言,不是脚本语言,运行要先编译,可是由于编译很快,实际上很容易当成一个脚原本执行,好比这个例子。或者显式的运行go build,go run,像docker/distribution项目的dockerfile这样。那么要实现一个"动态"运行golang的工具要作的就是:定义一种类型的任务,用户的测试脚本只要实现这种任务的interface,客户端就能够装载这种脚本编译运行。具体举例以下。docker
// 1. 定义一个TTask做为interface
type TTask interface {
Name() string
Run() int
}
// 2. 用户的测试脚本实现这个interface
// New ....
func newhello() task.TTask {
return &hellotask{}
}
type hellotask struct {
}
func (h *hellotask) Name() string {
return "task"
}
func (h *hellotask) Run() int {
time.Sleep(time.Microsecond * 10)
return 0
}
// 3. 实现一种注册式的插件机制,让用户的任务注册进来
var tasksets = make(map[string]NewFunc, 0)
func Register(newfunc NewFunc) {
t := newfunc()
_, registered := tasksets[t.Name()]
if registered {
panic(fmt.Sprintf("TTask named %s already registered", t.Name()))
}
tasksets[t.Name()] = newfunc
}
// 用户脚本中要注册他的脚本
Register(task.NewFunc(newhello))
// 4. 测试客户端不关心用户脚本的实现细节,运行tasksets里面TTask就能够了
func main() {
for _, f := range tasksets {
f().Run()
...
}
}复制代码
一个更复杂一点的例子在这里。apache
首先实现测试任务,使用job是很合适不过的,设置parallelism并发运行。bash
其次要实现任务的动态添加和挂载,可使用k8s的configmap来实现。使用configmap来保存用户的脚本,运行agent的时候将脚本自动挂载到agent的容器对应路径,容器启动脚本中加入build流程,这样就能很方便的实现一种"动态"的运行golang脚本的效果了。并发
当压力测试使用多个节点的时候,咱们每每须要同时观测测试客户端和服务端的cpu等资源监控,由于客户端已经自然的运行在k8s上了,能够直接使用k8s的监控设施。
另外测试工具的设计并无局限在测试运行在k8s上的server,可是若是恰好,被测试的对象也运行在k8s上,那么也能够很方便的或者server的宿主机metrics,若是不是,那么server端就须要装一个收集metric的deamon实现一样的效果了。分布式
dashboard支持查看测试任务,每一个任务有一个最近运行的记录和建立时间。
编辑一个测试项目,测试脚本是用golang编辑的,须要实现一个TTaskSet 的interface。支持设置任务的goroutine和运行时间,权重,设置权重以后goroutine数量会在多个taskset之间分配,一个taskset又能够添加多个task。taskset并发运行,一个taskset中的task串行运行,这样设计的好处是能够知足用户并发,串行,带context的串行多种需求,很是灵活。任务能够选择运行的节点,多个节点并发测试。
运行完测试的效果,目前尚未加入测试中的client,server资源监控,可是简单的测试统计已经有了。如图是测试的一个运行在1G虚拟机的nginx容器的测试结果。测试结果同时有各个节点的运行结果和汇总结果,同时绘制latency的百分位图。
完整项目地址在 github.com/arlert/ymir 欢迎拍砖。