本报告次要分为两局部,性能测试和音讯可靠性测试。前者次要关注吞吐,延时,同时在线用户等,即通常所说的性能指标。后者次要模仿实在环境(比方离线,在线,弱网)音讯通道的可靠性。
先说论断,对于容量和性能:
性能及容量总结
服务器资源:8 核 16G 内存,6 个机械磁盘,每个磁盘 100G,用于 mongo 分片,10MB 带宽。
容量:用户容量 10 万以上,音讯条数 10 亿条。
性能评估:同时在线用户 10 万,每秒钟发送音讯 900 条,音讯延时 1 秒(从发送者收回音讯到接管到音讯)
可靠性总结
启动 sdk,模仿 50 个用户在线、离线状况,音讯可靠性 100%。
发送 10 万音讯,有 3 条失败,其余音讯都能被对方准确收到,并胜利落地本地 db。对于失败的 3 条音讯,接管方的确没有收到,零碎音讯是统一的。
我的项目介绍
OpenIM 是由前微信技术专家打造的开源的即时通讯组件。Open-IM 包含 IM 服务端和客户端 SDK,是一套整体的解决方案,代码开源,所有可控,
github 地址:https://github.com/OpenIMSDK/…
开发者核心: https://doc.rentsoft.cn/#/
在单机的状况下,模仿线上用户发消息流程,在线用户量和音讯量达到一定量级后,零碎 CPU、内存、磁盘占用、以及音讯时延状况。以确定用户群体达到一定量级后,对服务器资源的事后评估。本次测试并不极限测试,一是因为生产环境原本都会有用户量和音讯量的限度,二是因为 OpenIM 的音讯模型,音讯发送首先都会通过 websocket 入库 kafka,实践上发送音讯的写入性能是两者的组合,而音讯发送的真正瓶颈理论在 mongodb 的随机读写。
测试过程
服务器资源:腾讯云主机(香港)1 台:linux Ubuntu 18.04.4 零碎,4 核 8G 内存,单块机械硬盘。5Mb 带宽。
测试条件:去掉音讯入库 mysql(因 mysql 仅用于治理后盾,不影响线上用户服务)。日志级别调整为 4 或更低。kafka 设置 2 个分区,msg_transfer 2 个。
测试流程:1 个客户端(成都,window pc,4 核 16G 内存)启动 1 万个协程,模仿用户与服务器建设 websocket 长连贯,间隔时间为随机 50-100 秒之间。两个客户端共模仿 2 万用户同时在线,发送音讯,察看音讯流转各个模块的解决能力,共计 2500 万条音讯,察看零碎内存、磁盘资源应用状况。
测试论断和剖析
| 关注指标 | 测试后果 |
| 同时在线人数 | 20000 个 |
| 网关接管音讯速度 | 150 条 /s(因为瓶颈不在此,成心管制发送速度,以确保 kafka 能被疾速生产入 mongodb)|
| mongodb 解决写入 | 300 条 /s(收件箱模型,导致音讯一拆为二)|
| CPU 使用率 | 约 50% |
| 内存使用率 | 约 4G(mongo 内存限度 2G,因为每个文档存储 5k 条音讯,理论理论索引量很小。redis 只存了用户 seq 映射关系,根本不占内存)|
| 发送音讯响应时长 | 均匀 70 毫秒 |
| 发送过程时延 | 平约 1 秒 |
| 磁盘空间 | mongo 中 5000 万条音讯占用 10G 磁盘,因为一拆为二的缘故,mongo 的 50000 万条音讯,理论为 2500 万条音讯。<br/> |
mongodb 数据状况
redis 数据状况
磁盘状态
<img src=”C:\Users\Administrator\Desktop\OpenIM\ 官网相干 \ 技术文章 \OpenIM 测试报告 \ 磁盘.png” alt=” 磁盘 ” style=”zoom:50%;” />
资源占用剖析
(1)redis 内存耗费极小,一个用户一条数据(包含 token 和 seq),和用户量成正比,3 万用户占用几十 M 内存。
(2)mongodb 如果去掉 cache,内存耗费极小,每个 document 寄存 5000 条音讯,与用户量和音讯量成正比,3 万用户,2500 万音讯,索引才 950K(更好的形式查看 mongo 耗费 cache 之外的内存)
(3)2500 万音讯,磁盘空间占用 10G。
(4)每秒钟 150 条音讯,cpu 整体占用 50%,即 2 核。
性能剖析
(1)性能瓶颈在 mongodb 写入操作,1 条音讯,须要依照发送者和接收者拆分 2 次,mongodb 写入 2 次,将来能够针对 mongodb 读写进一步优化。
(2)对于 cpu 耗费较大的模块,将来做一次整体优化。
(3)性能很安稳,不会随着数据量减少而升高。机械磁盘 iops 达到 200 根本达到了设施的极限
单机性能预估
服务器资源:8 核 16G 内存,6 个磁盘,每个磁盘 100G,用于 mongo 分片,10MB 带宽。
性能评估:同时在线用户 10 万,每秒钟发送音讯 900 条,音讯延时 1 秒(从发送者收回音讯到接管到音讯)
| 模块 | 性能状况 | 阐明 |
| msg_gateway | 部署多个 |,同时在线 5 万 *2=10 万 |
| mongodb | 6 分片,每个磁盘对应一个分片 | 1800 条 / 每秒音讯入库 |
| CPU 使用率 | 约 100% | 须要优化模块 缩小 cpu 耗费 |
| 内存使用率 | 小于 8G(mongo 内存限度 2G)| 如果内存充裕能够减少 mongodb 的 cache 大小 |
| 发送音讯响应时长 | 均匀 70ms | |
| 发送过程时延 | 平约 1s | 从发送者到接收者 |
| 10 亿条音讯,磁盘空间 | 占用 40*100G 磁盘,每个磁盘大略占用 70G 空间 | 对于群聊属于扩散写,磁盘耗费较大。整体要思考磁盘空间充裕 |
将来工作优化
(1)mongo 集群部署,反对上亿用户同时在线,千亿级音讯;
(2)简化集群部署;
(3)数据备份、复原工具;
以上次要对服务端性能做了一个大抵测试,但一套残缺的 IM 解决方案,不仅仅是服务端的工作。实际上,客户端重要性毋庸置疑,具体包含如何利用 seq 和服务端同步音讯,如果保障音讯收发的时序,如何回调客户端(会话扭转、新增,新音讯),音讯落地本地 db,seq 同步,音讯推拉如何联合以确保音讯收发可靠性。
音讯可达率(可靠性)测试
相比于性能测试,实际上,音讯的可达性(可靠性)更为重要。所以,咱们在做性能测试的同时,也要对音讯的可达性(可靠性)进行测试,如果不能保障音讯收发的正确性,再高的性能也是徒劳。本文重点总结对于 OpenIM 对于音讯可达性测试的计划、过程以及后果。先说论断,OpenIM 音讯可达率 100%,大家能够放心使用在生产环境中。seq 对齐和同步机制,保障了 OpenIM 的音讯可达性是业界当先的。
音讯可达性(可靠性)的定义
IM 音讯零碎的可靠性,通常就是指音讯投递的可靠性,即咱们常常听到的“音讯必达”,通常用音讯的不失落和不反复两个技术指标来示意。确保音讯被发送后,能被接收者收到。因为网络环境的复杂性,以及用户在线的不确定性,音讯的可靠性(不失落、不反复)无疑是 IM 零碎的外围指标,也是 IM 零碎实现中的难点之一。总体来说,IM 零碎的音讯“可靠性”,通常就是指聊天音讯投递的可靠性(精确的说,这个“音讯”是狭义的,因为还存用户看不见的各种指令和告诉,包含但不限于进群退群告诉、好友增加告诉等,为了不便形容,统称“音讯”)。
从音讯发送者和接收者用户行为来讲,音讯“可靠性”应该分为以下几种状况:
(1)发送失败,对于这种状况 IM 零碎必须要感知到,明确反馈发送方。如果此音讯没有发送胜利,发送方能够抉择重试或者稍后再试。
(2)发送胜利,如果接管方处在“在线”状态,应该立刻收到此音讯。如果接管方处在“离线”状态不能收到音讯,一旦上线则立即收到音讯。
(3)音讯不能反复,用数学术语示意:“有且仅有这条音讯”,如果反复了,可能表白的意思就变了。总之,一个商用 IM 零碎,必须蕴含音讯“可靠性”逻辑,能力谈根本可用,这是 IM 零碎最根本也是最外围的逻辑。
模仿场景 & 测试计划
互联网实在场景简单,但客户端大体能够分为两种状况:(1)发送音讯时,接管方在线,能收到音讯;(2)发送音讯时接管方不在线,登录后能收到离线音讯。咱们用测试程序模仿互联网客户端各种场景,依照登录、发送音讯、接管音讯的状况,把测试客户端分为以下 2 种类型:
(1)启动测试时离线,随机 sleep 0-60 秒后登录,发送音讯,且接管音讯
(2)启动测试时离线,随机 sleep 0-60 秒后登录,不发送音讯,只接管音讯
test.ReliabilityTest(oneClientSendMsgNum, intervalSleepMs, imIP, randSleepMaxSecond, testClientNum)
在理论测试中共计 50 个客户端,约 25 个(50% 概率)客户端不发送只接管音讯,约 25 个(50% 概率)客户端发送且接管音讯。
发送模式:每个客户端随机抉择其余客户端作为音讯接收者;
测试预期:每一条发送胜利的 MsgID,都能在接管的音讯列表中找到,同样,每一条接管到的 MsgID,都能在发送胜利的音讯列表中找到。
具体做法:(1)音讯发送胜利后,通过 OnSuccess 回调,记录 MsgID;收到新音讯后回调 OnRecvNewMessage,记录 MsgID;(2)周期性比照两个音讯列表,确认是否完全一致;
测试后果
| 发送音讯客户端 | 接管音讯客户端 | 预设发送音讯总量 | 发送胜利条数 | 发送失败条数 | 接管音讯条数 | |
| 25 个 | 50 个 | 100000 条 | 99997 | 3 | 99997 | |
发送数据 100000 条,其中失败 3 条,9999997 条胜利,接管方胜利接管 9999997 条音讯(接管方胜利接管到音讯,写入本地 db,并能触发音讯回调)
每一条发送胜利的音讯,对方都能精确接管到,无论接管方在音讯发送时的登录状态是在线还是离线。
每一条发送失败的音讯,对方都不会收到。
测试程序
main/main.go
intervalSleepMs := 1
randSleepMaxSecond := 30
imIP := "127.0.0.1" //OpenIM ip
oneClientSendMsgNum := 4000 // 每个客户端发送的音讯条数
testClientNum := 50 // 同时启动压测客户端数量
func main() {reliabilityTest()
}
注意事项:
(1)管制压力,因为 sdk 须要写本地 db,客户端会成为压力瓶颈。
(2)压测客户端日志会影响测试性能。
老本比照
此表格是某 IM 云平台的价格,如果依照 10 万月活,存储三年音讯来算,大略每年须要领取 15 万。而采纳 OpenIM 只须要洽购云主机,每年老本约 0.8 万。