websocket服务器测试
代码地址:github.com/buexplain/netsvr
netsvr
网关进程,是websocket服务器,运行在Linux虚拟机内,启动后的初始内存:19KiBbusiness
业务进程,是模拟业务逻辑的服务器端的,运行在宿主机上stress
压测进程,是模拟客户端的,运行在宿主机上
宿主机配置
Linux虚拟机配置
场景1:一万个只有心跳的连接
压测代码逻辑:
- 分三个阶段,每个阶段发起一部分连接,每个阶段连接建立完毕后,暂停60秒后,再进行下一个阶段,最后一个阶段不做暂停操作。
- 每个连接,每隔30秒,发起一次心跳,服务端会响应心跳。
- 所有阶段的连接建立完毕后,持续3分钟后,输出统计结果,关闭连接。
netsvr
监控,该图是所有连接建立完毕,持续1分钟后的截图
该图是压测代码的运行日志与统计结果
场景2:一万个单播的连接
压测代码逻辑:
- 分三个阶段,每个阶段发起一部分连接,每个阶段连接建立完毕后,暂停60秒后,再进行下一个阶段,最后一个阶段不做暂停操作。
- 每个连接,每隔30秒,发起一次心跳,服务端会响应心跳。
- 每个连接间,每隔5秒向服务器发起一次单播(自己发给自己),消息长度是128字节,注意这个长度不是数据打包后的长度。
- 所有阶段的连接建立完毕后,持续3分钟后,输出统计结果,关闭连接。
netsvr
监控,该图是所有连接建立完毕,持续1分钟后的截图
该图是压测代码的运行日志与统计结果
场景3:一万个批量单播的连接
压测代码逻辑:
- 分三个阶段,每个阶段发起一部分连接,每个阶段连接建立完毕后,暂停60秒后,再进行下一个阶段,最后一个阶段不做暂停操作。
- 每个连接,每隔30秒,发起一次心跳,服务端会响应心跳。
- 每个连接间,每隔5秒向服务器发起一次批量单播(自己发给自己),消息长度是128字节,注意这个长度不是数据打包后的长度。
- 所有阶段的连接建立完毕后,持续3分钟后,输出统计结果,关闭连接。
netsvr
监控,该图是所有连接建立完毕,持续1分钟后的截图
该图是压测代码的运行日志与统计结果
场景4:一万个组播的连接
压测代码逻辑:
- 分三个阶段,每个阶段发起一部分连接,每个阶段连接建立完毕后,暂停60秒后,再进行下一个阶段,最后一个阶段不做暂停操作。
- 每个连接,每隔30秒,发起一次心跳,服务端会响应心跳。
- 每个连接间,每隔5秒向服务器发起一次组播(一次性给多个人发消息),目标连接数是15个,消息长度是128字节,注意这个长度不是数据打包后的长度。
- 所有阶段的连接建立完毕后,持续3分钟后,输出统计结果,关闭连接。
netsvr
监控,该图是所有连接建立完毕,持续1分钟后的截图
该图是压测代码的运行日志与统计结果
场景5:一千个订阅主题、取消订阅主题、按主题发布数据的连接
压测代码逻辑:
- 分三个阶段,每个阶段发起一部分连接,每个阶段连接建立完毕后,暂停60秒后,再进行下一个阶段,最后一个阶段不做暂停操作。
- 每个连接,每隔30秒,发起一次心跳,服务端会响应心跳。
- 每个连接,每隔5秒向服务器发起一次订阅100个主题、取消订阅50个主题、基于1个主题发布128字节的数据。
- 所有阶段的连接建立完毕后,持续3分钟后,输出统计结果,关闭连接。
netsvr
监控,该图是所有连接建立完毕,持续1分钟后的截图
该图是压测代码的运行日志与统计结果
当所有连接建立完毕后,netsvr
中的主题数量是1225个主题,平均每个主题被303个连接订阅。
场景6:一个连接广播给一万个连接
压测代码逻辑:
- 分三个阶段,每个阶段发起一部分连接,每个阶段连接建立完毕后,暂停60秒后,再进行下一个阶段,最后一个阶段不做暂停操作。
- 每个连接,每隔30秒,发起一次心跳,服务端会响应心跳。
- 1个连接,每隔5秒向服务器发起一次广播,消息长度是128字节,注意这个长度不是数据打包后的长度。
- 所有阶段的连接建立完毕后,持续3分钟后,输出统计结果,关闭连接。
netsvr
监控,该图是所有连接建立完毕,持续1分钟后的截图
该图是压测代码的运行日志与统计结果
场景7:一万个登录、登出操作的连接
压测代码逻辑:
- 分三个阶段,每个阶段发起一部分连接,每个阶段连接建立完毕后,暂停60秒后,再进行下一个阶段,最后一个阶段不做暂停操作。
- 每个连接,每隔30秒,发起一次心跳,服务端会响应心跳。
- 每个连接,每隔5秒向服务器发起一次登录、登出操作,登录操作是:往网关存储新的uniqId、1kb的session数据、订阅10个主题,登出操作是:移除连接在网关中的uniqId、session、主题。
- 所有阶段的连接建立完毕后,持续3分钟后,输出统计结果,关闭连接。
netsvr
监控,该图是所有连接建立完毕,持续1分钟后的截图
该图是压测代码的运行日志与统计结果
当所有连接建立完毕后,netsvr
中的主题数量是1226个主题,平均每个主题被38个连接订阅。
场景8:综合以上场景做一个全套测试
压测逻辑太冗长了,不再描述,只给压测配置:
# 日志级别 debug、info、warn、error
LogLevel = "debug"
# customer服务的websocket连接地址
CustomerWsAddress = "ws://192.168.241.2:6060/netsvr"
# worker服务的监听地址
WorkerListenAddress = "192.168.241.2:6061"
# 该值与netsvr.toml的配置保持一致
ConnOpenCustomUniqIdKey = ""
# 表示消息被哪个workerId的业务进程处理
WorkerId = 1
# 每个连接间隔多少秒进行心跳
Heartbeat = 30
# 是否并发初始化每个压测模块
Concurrent = true
# 当所有连接建立完毕后的持续时间,单位秒
Suspend = 180
# 沉默的连接
[Silent]
Enable = true
Step = [
#每个阶段初始化的连接数、每秒初始化的连接数、本阶段初始化完毕后的暂停秒数
{ ConnNum = 600, ConnectNum = 100, Suspend = 60 },
{ ConnNum = 600, ConnectNum = 100, Suspend = 60 },
{ ConnNum = 800, ConnectNum = 100, Suspend = 60 },
]
# 疯狂登录登出的连接
[Sign]
Enable = true
# 每个连接间隔多少秒进行一次登录、登出操作
MessageInterval = 5
Step = [
{ ConnNum = 50, ConnectNum = 100, Suspend = 60 },
{ ConnNum = 100, ConnectNum = 100, Suspend = 60 },
{ ConnNum = 200, ConnectNum = 100, Suspend = 60 },
]
# 疯狂单播的连接
[SingleCast]
Enable = true
# 单播时发送的消息大小
MessageLen = 128
# 每个连接间隔多少秒进行一次单播操作
MessageInterval = 5
Step = [
{ ConnNum = 50, ConnectNum = 100, Suspend = 60 },
{ ConnNum = 100, ConnectNum = 100, Suspend = 60 },
{ ConnNum = 200, ConnectNum = 100, Suspend = 60 },
]
# 疯狂批量单播的连接
[SingleCastBulk]
Enable = true
MessageLen = 256
# 一组包含的uniqId数量
UniqIdNum = 15
# 每个连接间隔多少秒进行一次批量单播操作
MessageInterval = 5
Step = [
{ ConnNum = 50, ConnectNum = 100, Suspend = 60 },
{ ConnNum = 100, ConnectNum = 100, Suspend = 60 },
{ ConnNum = 200, ConnectNum = 100, Suspend = 60 },
]
# 疯狂组播的连接
[Multicast]
Enable = true
MessageLen = 256
# 一组包含的uniqId数量
UniqIdNum = 15
# 每个连接间隔多少秒进行一次组播操作
MessageInterval = 5
Step = [
{ ConnNum = 50, ConnectNum = 100, Suspend = 60 },
{ ConnNum = 100, ConnectNum = 100, Suspend = 60 },
{ ConnNum = 200, ConnectNum = 100, Suspend = 60 },
]
# 疯狂订阅、取消订阅、发布,下面这套配置下,主题总数是1225个主题,平均每个主题被80个连接订阅,当然因为机器性能、网络等原因,实际订阅数可能不一样
[Topic]
Enable = true
# 每个连接的备选主题数量,该值是随机产生的,该值越大,则一个主题会被多个连接订阅的概率越小
AlternateTopicNum = 600
# 主题字符串的长度,4有1413720种排列 3有42840种排列,2有1260种排列,该值越大,则一个主题会被多个连接订阅的概率越小
AlternateTopicLen = 2
# 连接建立的步骤
Step = [
{ ConnNum = 50, ConnectNum = 100, Suspend = 60 },
{ ConnNum = 100, ConnectNum = 100, Suspend = 60 },
{ ConnNum = 200, ConnectNum = 100, Suspend = 60 },
]
[Topic.Subscribe]
# 运行模式 0 延长多少秒执行,1 间隔多少秒执行一次
Mode = 1
# 延长或间隔的秒数
ModeSecond = 5
# 每次订阅的主题数量,该值是轮询AlternateTopicNum得到的,第零个主题一定会被订阅
TopicNum = 100
[Topic.Unsubscribe]
# 运行模式 0 延长多少秒执行,1 间隔多少秒执行一次
Mode = 1
# 延长或间隔的秒数
ModeSecond = 5
# 每次取消订阅的主题数量,该值是轮询AlternateTopicNum得到的,但是不会取消连接订阅的第零个主题
TopicNum = 50
[Topic.Publish]
# 发布数据的大小
MessageLen = 512
# 运行模式 0 延长多少秒执行,1 间隔多少秒执行一次
Mode = 1
# 延长或间隔的秒数
ModeSecond = 5
# 每次发布消息的主题数量,该值是轮询AlternateTopicNum得到的,但是连接订阅的第零个主题是一定会被用于消息发布的
TopicNum = 1
# 疯狂广播的连接
[Broadcast]
Enable = true
MessageLen = 1024
# 每个连接间隔多少秒进行一次广播操作
MessageInterval = 5
Step = [
{ ConnNum = 2, ConnectNum = 10, Suspend = 60 },
{ ConnNum = 4, ConnectNum = 10, Suspend = 60 },
{ ConnNum = 6, ConnectNum = 10, Suspend = 60 },
]
netsvr
监控,该图是所有连接建立完毕,持续1分钟后的截图
该图是压测代码的运行日志与统计结果
总结
在以上场景下,github.com/buexplain/netsvr 的代码运行稳定。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: