关于push系统对比与性能指标的讨论
很多同行比较关心go语言在实现push系统上的性能问题,单机性能究竟如何,能否和其他语言实现的类似系统做对比么?甚至问如果是创业,第三方云推送平台 , 推荐哪个?
其实各大厂都有类似的push系统,市场上也有类似功能的云服务 。包括我们公司早期也有erlang , nodejs实现的类似系统,也一度被公司要求做类似的对比测试 。我感觉在讨论对比数据的时候 , 很难保证大家环境和需求的统一 , 我只能说下我这里的体会,数据是有的,但这个数据前面估计会有很多定语~
第一个重要指标:单机的连接数指标
做过长连接的同行,应该有体会 , 如果在稳定连接情况下,连接数这个指标,在没有网络吞吐情况下对比,其实意义往往不大,维持连接消耗cpu资源很?。刻趿觮cp协议栈会占约4k的内存开销 , 系统参数调整后,我们单机测试数据,最高也是可以达到单实例300w长连接 。但做更高的测试,我个人感觉意义不大 。
因为实际网络环境下,单实例300w长连接,从理论上算压力就很大:实际弱网络环境下,移动客户端的断线率很高,假设每秒有1000分之一的用户断线重连 。300w长连接,每秒新建连接达到3w,这同时连入的3w用户,要进行注册,加载离线存储等对内rpc调用,另外300w长连接的用户心跳需要维持,假设心跳300s一次,心跳包每秒需要1w tps 。单播和多播数据的转发,广播数据的转发 , 本身也要响应内部的rpc调用,300w长连接情况下 , gc带来的压力,内部接口的响应延迟能否稳定保障 。这些集中在一个实例中 , 可用性是一个挑战 。所以线上单实例不会hold很高的长连接,实际情况也要根据接入客户端网络状况来决定 。
第二个重要指标:消息系统的内存使用量指标
这一点上,使用go语言情况下,由于协程的原因,会有一部分额外开销 。但是要做两个推送系统的对比 , 也有些需要确定问题 。比如系统从设计上是否需要全双工(即读写是否需要同时进行)如果半双工,理论上对一个用户的连接只需要使用一个协程即可(这种情况下,对用户的断线检测可能会有延时),如果是全双工,那读/写各一个协程 。两种场景内存开销是有区别的 。
另外测试数据的大小往往决定我们对连接上设置的读写buffer是多大,是全局复用的,还是每个连接上独享的,还是动态申请的 。另外是否全双工也决定buffer怎么开 。不同的策略,可能在不同情况的测试中表现不一样 。
第三个重要指标:每秒消息下发量
这一点上,也要看我们对消息到达的QoS级别(回复ack策略区别),另外看架构策略,每种策略有其更适用的场景,是纯粹推?还是推拉结合?甚至是否开启了消息日志?日志库的实现机制、以及缓冲开多大?flush策略……这些都影响整个系统的吞吐量 。
另外为了HA,增加了内部通信成本 , 为了避免一些小概率事件,提供闪断补偿策略,这些都要考虑进去 。如果所有的都去掉,那就是比较基础库的性能了 。
所以我只能给出大概数据 , 24核,64G的服务器上,在QoS为message at least,纯粹推,消息体256B~1kB情况下 , 单个实例100w实际用户(200w+)协程,峰值可以达到2~5w的QPS...内存可以稳定在25G左右,gc时间在200~800ms左右(还有优化空间) 。
我们正常线上单实例用户控制在80w以内,单机最多两个实例 。事实上,整个系统在推送的需求上,对高峰的输出不是提速,往往是进行限速,以防push系统瞬时的高吞吐量,转化成对接入方业务服务器的ddos攻击所以对于性能上,我感觉大家可以放心使用 , 至少在我们这个量级上,经受过考验,go1.5到来后,确实有之前投资又增值了的感觉 。
- redis实现延时消息队列 redis消息时间过长
- 使用redis实现分布式锁及其优化 redis分布式性能
- redis事务实现原理 在事务中使用redis
- redis map底层实现 redis多个map命令
- mongodb表设计 mongodb实现动态表单
- redis实现排行榜思路 redis全站排行榜
- redis实现手机验证码的缓存 redis实现验证码
- redis实现限流 redismap限制
- mysql分布式存储实现 分布式mysql集群部署
- 将数据保存到文件中c语言 将数据保存到mongodb
