go语言http长连接的简单介绍( 二 )


因为实际网络环境下,单实例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到来后 , 确实有之前投资又增值了的感觉 。
消息系统架构介绍
下面是对消息系统的大概介绍,之前一些同学可能在gopher china上可以看到分享,这里简单讲解下架构和各个组件功能,额外补充一些当时遗漏的信息:
架构图如下 , 所有的service都 written by golang.
几个大概重要组件介绍如下:
dispatcher service根据客户端请求信息,将应网络和区域的长连接服务器的,一组IP传送给客户端 。客户端根据返回的IP , 建立长连接,连接Room service.
room Service,长连接网关 , hold用户连接,并将用户注册进register service,本身也做一些接入安全策略、白名单、IP限制等 。
register service是我们全局session存储组件,存储和索引用户的相关信息 , 以供获取和查询 。
coordinator service用来转发用户的上行数据,包括接入方订阅的用户状态信息的回调,另外做需要协调各个组件的异步操作 , 比如kick用户操作,需要从register拿出其他用户做异步操作.

推荐阅读