目录
1.项目背景
目前常用的压测工具一般都是针对QPS这一个单一指标进行考量。即使支持编写脚本的工具也只是通过参数化模拟用户。但是实际用户是使用单独设备请求服务器,即一个用户就是一个tcp连接。
所以为了更真实的模拟用户行为,我们需要通过一个tcp连接模拟一个用户,并通过代码方式实现用户的真实请求行为。C端及中台产研中心云平台部质量保障团队自研的“仿真压测系统”。独有的QPS动态可控技术,支持固定URL压测、参数化、Websocket协议压测、中间件、数据库等的压测,模拟用户真实轨迹,通过用户侧,服务端,DB进行数据一致性和正确性自动检验,打造真正的全链路仿真压测,该系统可扩展性强,稳定性高,目前已多次支持公司级各类大型活动的仿真全链路压测,为线上服务的稳定运行提供了强有力的质量保障。
经过四年的打磨如今借此机会与大家分享一下心路历程,积极讨论,欢迎提出意见,希望可以帮助我们进一步成长。(文中引用均为测试数据)
2.仿真压测系统成型之路
2.1
工具选型
► 2.1.1 现有的压测工具对比
图1-1
► 2.1.2 Locust发压client比较
图1-2
结合以上比较结果,目前没有合适的压测工具可以直接满足我们的压测需求,最终决定用Locust做框架,首先它是一款易于使用的分布式负载测试工具,完全基于事件,单机并发能力高,并发机制是协程,其次二次开发潜力比较大。
发压的请求client采用fasthttp, 据说是目前golang性能最好的http库,原理是利用worker复用goroutine,减轻runtime调度协程的压力,相对于自带的net/http(每个连接都需要新建一个goroutine),性能有10倍的提升。省略一千字,直接上干货。
► 2.1.3 仿真压测系统特性:
-
分布式部署;
-
固定URL压测;
-
参数化脚本压测;
-
Websocket协议压测;
-
其他协议UDP、http2、 RTMP/HLS、MQTT(golang可以实现的协议都可满足)
-
Redis直压;
-
Kafka直压
-
Mysql直压;
-
自定义脚本压测(仿真压测,全链路数据对账);
-
动态可控QPS、TCP;
-
秒级启动/停止,结果收集即停即展示,无需等待
……
► 2.1. 4 实现难点分析
模拟百万用户创建TCP/ websocket连接;长时间保持连接不断开;集中发压;
部分代码如下:
go func() {
for {
select
case data := <-r.stats.messageToRunnerChan:
data["user_count"] = r.numClients
r.outputOnEevent(data)
case <-r.closeChan:
Events.Publish("boomer:quit")
r.stop()
wg.Done()
return
}
}
}()
集中发压
curTime := myStatus.Ct
statusTime := myStatus.St
c := time.After(time.Duration(statusTime-curTime) * time.Second)
<-c
miaosha(uidToken, &myStatus, myLog)
保持长链接
func wsWorker() {
ws, err := websocket.Dial(wsUrl, "", origin)
if err != nil {
log.Println(err)
return
}
defer func() {
if p := recover(); p != nil {
log.Println(p)
}
erc := ws.Close()
if erc != nil {
log.Println(erc)
}
}()
go func() {
ws.Write([]byte("0"))
var t = time.Tick(time.Second * 30)
for range t {
if ws == nil {
continue
}
ws.Write([]byte("0"))
fmt.Println("send 0 to websocket ok!")
}
}()
for {
select {
case <-stopChannel:
return
default:
var msg = make([]byte, 512)
start := time.Now()
n, err := ws.Read(msg)
log.Println(string(msg[0:n]))
elapsed := time.Since(start)
if myDebug {
log.Println(string(msg))
}
if err != nil {
log.Printf("Error: %s", err.Error())
}
}
}
}
2.2
日常使用截图
图2-平台首页
图3-实时监控压测页面,总请求数、实时qps、响应时间、发压机cpu占用等指标。
图4-压测空接口,服务器监控截图, Nginx的峰值QPS可以达到596万。
图5-压测redis时监控截图,单个节点的实时监控等都可以一览无余
3. 818台网实战开始
工欲善其事,必先利其器,利器已有,剧本安排上。
晚会当天数以万计的用户通过手机app参与活动,从白天开始“预约红包”,晚上八点晚会开始后用户开始陆陆续续登录app“领取预约红包”;随着主持人口播,第一轮“集卡”活动开始……人数慢慢增多,到了最激动人心的时候。“一元秒新车”开始,QPS狂飙,TCP连接数也达到了峰值100W。
开始实战:
控制台:各部门注意,入口已经放开,流量开始进入;目前“预约红包”阶段
仿真压测:收到,每五分钟递增1w用户(1TCP模拟1用户以下通用TCP数代指用户数),QPS200(用户进入活动页面,预约红包、查看规则、查看介绍等大概每人5次请求)
图6-由于发压机数量32台,每个机器限制QPS7所以总QPS就是224
控制台:晚会开始,“预约红包”可领状态,“见面礼红包”已开启,“连续红包”已开启,第一场大咖讲话马上开启……
仿真压测:明白,TCP调整到20W,QPS2W(用户操作5次集中在1分钟以内)
图7-动态调整QPS、TCP连接数按钮
图8-设置TCP连接数、QPS、步增等
图9-设置生效,TCP、QPS稳定保持在设定值
控制台:抽盲盒活动进入倒计时
仿真压测:copy,TCP调整到30W,QPS10W(用户3秒内点击10~15次提交一次请求到服务器)
图10-设置生效,TCP、QPS稳定保持在设定值
控制台:时间来到最终环节,“一元秒新车”,倒计时开启
仿真压测:拼手速的时候到了,TCP100W,QPS100W(秒杀只可以提交一次)走起
图11-设置生效,TCP、QPS稳定保持在设定值
至此,晚会结束,仿真压测却并没有结束,还有最后一环--“对账”。仿真压测会把接口返回用户的数据记录到kafka中,最后入库,与服务器的数据进行对账,确保每条数据的正确性。
图12-服务侧数据与用户侧数据进行对账
看一下动态调整QPS的完美曲线,随着用户增长以及QPS增长的仿真图
图13-仿真模拟用户递增的曲线
图14-服务器监控截图,仿真用户全部走websocket协议,通过“状态机”下发指令、接收指令
图15-Redis 监控截图
图16-云服务器LB截图
图17-云服务器LB截图
图18-云服务器LB截图
图19-仿真压测完成,服务侧奖品发放明细
图20-仿真侧用户领取奖品明细以及对账情况
数据完美对上。
4. 总结
由于篇幅受限,想说的很多,质量保障团队也做了很多,比如灾备演练,模拟服务器满载、域名切换、服务器宕机、机房切换等等。关于测试方面的问题欢迎私下讨论。
以下是我收集到的比较好的学习教程资源,虽然不是什么很值钱的东西,如果你刚好需要,可以评论区,留言【777】直接拿走就好了
各位想获取资料的朋友请点赞 + 评论 + 收藏,三连!
三连之后我会在评论区挨个私信发给你们~