动态 QPS 压测模型【Go 语言】
之前写 Kafka Client Go 实践的时候,跟一位粉丝交流,Go 语言的 channel 实现和 Java 的多线程实现的性能问题。就想做一次两者的性能测试进行对比。可惜 Go 语言用得少,还没形成快速进行性能测试的基础能力。所以得建设一些基础设施之后才行,今天分享一下,基于 Go 语言的动态 QPS 压测模型实现,算是基础能力建设的一部分了。
本文基于上期提到的 Go 语言的协程池,查到很多资料,有的不建议复用协程。原因主要两点:
协程本身创建开销非常小,可以忽略。频繁创建和销毁协程并不会导致明显的性能瓶颈。
协程设计本来基于简单化,使用协程池破坏了使用便捷性
对于第一个观点,以我现在知识和实践经验来说,不是太认同。任何资源的创建和销毁都会消耗资源。假如不适用协程池,那么每一个性能测试任务都消耗一个协程,每秒几万级别的资源创建和销毁事件,总觉得会很大影响施压机的性能。
第二观点,无法反驳,水平不够。就我自己的经验来说,协程池最大的好处是可以控制并发达到控制压测的目的。避免给其他服务造成过载的情况。在实际实践中,限制最大的请求压力,也有很多使用场景,这里不一一叙述。
思路
首先基于Go语言协程池实现,我增加了一个方法,实现将一个任务使用协程池发送 N 次,也就是添加 N 次任务即可。这里我复用 FunTester 在处理大量性能任务的一个经验,就是每次发送任务的数量进行设置。例如:需要任务执行 1000 次,那么分成 100 次,每次打包发送 10 个任务串行。这样可以避免使用更多的线程/协程。增加单个线程/协程每次执行任务的时长,避免下上文切换(协程切换也有成本,没找到对应专业名词),这个做法在 Java 实践中,效果非常明显。
这里的SingleTimes
默认值是 10,这个根据实际任务执行的速度调整,我自己还没进行对比测试。
接收控制命令
这里依旧使用控制台输入当做控制命令的输入源,方法比较简单。
方法如下:
用例 Demo
这里有个坑,如果使用 Go 单元测试无法正常使用控制台输入。所以本次演示使用main
方法执行测试用例了。
最后一行,其实有些多余,因为通常使用手动结束进程来结束用例。
通过这个实现,感觉 Go 语言对使用function
当做参数真的非常流畅。这一点 Java N 个function
实现类着实让我有点懵逼。相比之下 Groovy 的closure
也非常丝滑,但由于 Groovy 语言特性,经常会导致意外错误发生。总结起来,Go 语言这方面是真香了。
版权声明: 本文为 InfoQ 作者【FunTester】的原创文章。
原文链接:【http://xie.infoq.cn/article/42cc6d7986b00d32f6cdbbabc】。文章转载请联系作者。
评论