websocket服务器测试

[TOC]

代码地址:github.com/buexplain/netsvr

  • netsvr 网关进程,是 websocket 服务器,运行在 Linux 虚拟机内,启动后的初始内存:19KiB
  • business 业务进程,是模拟业务逻辑的服务器端的,运行在宿主机上
  • stress 压测进程,是模拟客户端的,运行在宿主机上

宿主机配置
宿主机配置
Linux 虚拟机配置
Linux虚拟机配置

场景 1:一万个只有心跳的连接#

压测代码逻辑:

  1. 分三个阶段,每个阶段发起一部分连接,每个阶段连接建立完毕后,暂停 60 秒后,再进行下一个阶段,最后一个阶段不做暂停操作。
  2. 每个连接,每隔 30 秒,发起一次心跳,服务端会响应心跳。
  3. 所有阶段的连接建立完毕后,持续 3 分钟后,输出统计结果,关闭连接。

netsvr 监控,该图是所有连接建立完毕,持续 1 分钟后的截图
websocket服务器测试
该图是压测代码的运行日志与统计结果
websocket服务器测试

场景 2:一万个单播的连接#

压测代码逻辑:

  1. 分三个阶段,每个阶段发起一部分连接,每个阶段连接建立完毕后,暂停 60 秒后,再进行下一个阶段,最后一个阶段不做暂停操作。
  2. 每个连接,每隔 30 秒,发起一次心跳,服务端会响应心跳。
  3. 每个连接间,每隔 5 秒向服务器发起一次单播(自己发给自己),消息长度是 128 字节,注意这个长度不是数据打包后的长度。
  4. 所有阶段的连接建立完毕后,持续 3 分钟后,输出统计结果,关闭连接。

netsvr 监控,该图是所有连接建立完毕,持续 1 分钟后的截图
websocket服务器测试
该图是压测代码的运行日志与统计结果
websocket服务器测试

场景 3:一万个批量单播的连接#

压测代码逻辑:

  1. 分三个阶段,每个阶段发起一部分连接,每个阶段连接建立完毕后,暂停 60 秒后,再进行下一个阶段,最后一个阶段不做暂停操作。
  2. 每个连接,每隔 30 秒,发起一次心跳,服务端会响应心跳。
  3. 每个连接间,每隔 5 秒向服务器发起一次批量单播(自己发给自己),消息长度是 128 字节,注意这个长度不是数据打包后的长度。
  4. 所有阶段的连接建立完毕后,持续 3 分钟后,输出统计结果,关闭连接。

netsvr 监控,该图是所有连接建立完毕,持续 1 分钟后的截图
websocket服务器测试
该图是压测代码的运行日志与统计结果
websocket服务器测试

场景 4:一万个组播的连接#

压测代码逻辑:

  1. 分三个阶段,每个阶段发起一部分连接,每个阶段连接建立完毕后,暂停 60 秒后,再进行下一个阶段,最后一个阶段不做暂停操作。
  2. 每个连接,每隔 30 秒,发起一次心跳,服务端会响应心跳。
  3. 每个连接间,每隔 5 秒向服务器发起一次组播(一次性给多个人发消息),目标连接数是 15 个,消息长度是 128 字节,注意这个长度不是数据打包后的长度。
  4. 所有阶段的连接建立完毕后,持续 3 分钟后,输出统计结果,关闭连接。

netsvr 监控,该图是所有连接建立完毕,持续 1 分钟后的截图
websocket服务器测试
该图是压测代码的运行日志与统计结果
websocket服务器测试

场景 5:一千个订阅主题、取消订阅主题、按主题发布数据的连接#

压测代码逻辑:

  1. 分三个阶段,每个阶段发起一部分连接,每个阶段连接建立完毕后,暂停 60 秒后,再进行下一个阶段,最后一个阶段不做暂停操作。
  2. 每个连接,每隔 30 秒,发起一次心跳,服务端会响应心跳。
  3. 每个连接,每隔 5 秒向服务器发起一次订阅 100 个主题、取消订阅 50 个主题、基于 1 个主题发布 128 字节的数据。
  4. 所有阶段的连接建立完毕后,持续 3 分钟后,输出统计结果,关闭连接。

netsvr 监控,该图是所有连接建立完毕,持续 1 分钟后的截图
websocket服务器测试
该图是压测代码的运行日志与统计结果
websocket服务器测试
当所有连接建立完毕后,netsvr 中的主题数量是 1225 个主题,平均每个主题被 303 个连接订阅。

场景 6:一个连接广播给一万个连接#

压测代码逻辑:

  1. 分三个阶段,每个阶段发起一部分连接,每个阶段连接建立完毕后,暂停 60 秒后,再进行下一个阶段,最后一个阶段不做暂停操作。
  2. 每个连接,每隔 30 秒,发起一次心跳,服务端会响应心跳。
  3. 1 个连接,每隔 5 秒向服务器发起一次广播,消息长度是 128 字节,注意这个长度不是数据打包后的长度。
  4. 所有阶段的连接建立完毕后,持续 3 分钟后,输出统计结果,关闭连接。

netsvr 监控,该图是所有连接建立完毕,持续 1 分钟后的截图
websocket服务器测试
该图是压测代码的运行日志与统计结果
websocket服务器测试

场景 7:一万个登录、登出操作的连接#

压测代码逻辑:

  1. 分三个阶段,每个阶段发起一部分连接,每个阶段连接建立完毕后,暂停 60 秒后,再进行下一个阶段,最后一个阶段不做暂停操作。
  2. 每个连接,每隔 30 秒,发起一次心跳,服务端会响应心跳。
  3. 每个连接,每隔 5 秒向服务器发起一次登录、登出操作,登录操作是:往网关存储新的 uniqId、1kb 的 session 数据、订阅 10 个主题,登出操作是:移除连接在网关中的 uniqId、session、主题。
  4. 所有阶段的连接建立完毕后,持续 3 分钟后,输出统计结果,关闭连接。

netsvr 监控,该图是所有连接建立完毕,持续 1 分钟后的截图
websocket服务器测试
该图是压测代码的运行日志与统计结果
websocket服务器测试
当所有连接建立完毕后,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 分钟后的截图
websocket服务器测试
该图是压测代码的运行日志与统计结果
websocket服务器测试

总结#

在以上场景下,github.com/buexplain/netsvr 的代码运行稳定。

本作品采用《CC 协议》,转载必须注明作者和本文链接
梦想星辰大海
讨论数量: 20

websocket 怎么压测

1年前 评论
梦想星辰大海 (楼主) 1年前

可以在生产环境使用该项目吗?

1年前 评论
梦想星辰大海 (楼主) 1年前
kureCC (作者) 1年前
梦想星辰大海 (楼主) 1年前
kureCC (作者) 1年前
梦想星辰大海 (楼主) 1年前

我比较好奇,怎么快速给一万客户端发消息

1年前 评论
梦想星辰大海 (楼主) 1年前
kureCC 1年前
梦想星辰大海 (楼主) 1年前
kureCC 1年前
梦想星辰大海 (楼主) 1年前
kureCC 1年前
lxzan 1年前

我们生产有个场景,客户会导入 excel 我们作为任务来处理,但是处理的时间会有一点长,目前是通过轮询来查看任务,请问可以用你的项目吗?我的想法是完成任务以后发个消息后续通过 websocket 来告诉前端。

1年前 评论
梦想星辰大海 (楼主) 1年前

大佬 请教下有什么比较简单的方式吗 是可以引入现成的包吗

1年前 评论
梦想星辰大海 (楼主) 1年前