乐趣区

tcp没用吗?为什么MOBA、“吃鸡”游戏不推荐用tcp协议

本文由云 + 社区发表作者:腾讯云游戏行业资深架构师 余国良

MOBA 类和“吃鸡”游戏为什么对网络延迟要求高?
我们知道,不同类型的游戏因为玩法、竞技程度不一样,采用的同步算法不一样,对网络延迟的要求也不一样。例如,MOBA 类游戏多使用帧同步为主要同步算法,竞技性也较高,无论从流畅性,还是从公平性要求来说,对响应延迟的要求都最高,根据业内经验,当客户端与服务器的网络延迟超过 150ms 时,会开始出现卡顿,当延迟超过 250ms 时,会对玩家操作造成较大影响,游戏无法公平进行。类似地,“吃鸡”游戏(如《绝地求生》)玩法对玩家坐标、动作的同步要求极高,延迟稍大导致的数据不一致对体验都会造成较大影响,其实时性要求接近 MOBA 类游戏。而对于传统 mmorpg 来说,多采用状态同步算法,以属性养成和装备获取为关注点,也有一定竞技性,出于对游戏流畅性的要求,对延迟也有一定要求,同步算法的优化程度不一样,这一要求也不一样,一般情况下为保证游戏正常进行,需要响应延迟保持在 300ms 以下。相比之下,对于炉石传说、斗地主、梦幻西游等回合制游戏来说,同时只有一个玩家在操作双方数据,无数据竞争,且时间粒度较粗,甚至可通过特效掩盖延迟,因此对网络延迟的要求不高,即便延迟达到 500ms~1000ms,游戏也能正常进行。这里,我们不对同步算法做进一步说明,重点说一下协议的问题。
传输层协议和延迟
不同传输层协议在可靠性、流量控制等方面都有差别,而这些技术细节会对延迟造成影响。tcp 追求的是完全可靠性和顺序性,丢包后会持续重传直至该包被确认,否则后续包也不会被上层接收,且重传采用指数避让策略,决定重传时间间隔的 RTO(retransmission timeout) 不可控制,linux 内核实现中最低值为 200ms,这样的机制会导致丢包率短暂升高的情况下应用层消息响应延迟急剧提高,并不适合实时性高、网络环境复杂的游戏。
加速方案
基于 udp 定制传输层协议,引入顺序性和适当程度或者可调节程度的可靠性,修改流控算法。适当放弃重传,如:设置最大重传次数,即使重传失败,也不需要重新建立连接。比较知名的 tcp 加速开源方案有:quic、enet、kcp、udt。其中,quic 是源自 google 的 tcp 替代方案,其主要目的是为了整合 TCP 协议的可靠性和 udp 协议的速度和效率,其主要特性包括:避免前序包阻塞、减少数据包、向前纠错、会话重启和并行下载等,然而 QUIC 对标的是 TCP+TLS+SPDY,相比其他方案更重,目前国内用于网络游戏较少。kcp 的作者是国内优秀开发者,社区也发展良好,kcp 的作者和社区开发者对 enet、kcp、udt 做了性能测试,详情可参见:https://github.com/skywind300…,从测试情况可以看到,kcp 表现不错,其次是 enet,表现最差的是 udt。不过,这里也提出一个问题,原始 enet 保留了 tcp 重传的指数避让特性,每次重传间隔还是乘以 2,默认 rto 也较高,这可能是测试中 enet 表现不如 kcp 的主要原因,如果对 enet 代码稍作调整,结果又当如何?这里,我们先排除传输性能,从其他方面对 enet 和 kcp 做一对比(满分 5 分):

我们对 libenet 略微做一些调整——默认 rtt 从 500ms 调整成 50ms, 去除超时重传的指数避让策略。Linux 下用 TC 命令模拟网络延迟和丢包率,控制延迟分别为 30ms, 50ms, 70ms,控制丢包率分别为 1%, 3%, 5%, 7%, 10%,在模拟出的不同网络环境下,对 tcp, 原始 enet 和改进后的 enet 进行了对比测试。
测试中考察两个性能指标:
1)平均响应时间;
2)响应时间超过 300ms 的包的比例。
libenet 的代码调整:

​ 图 1 调整默认 RTT 为 50ms

图 2 取消指数避让
tc 命令如下:
模拟延迟 100ms(rtt 为 200ms):tc qdisc add dev eth0 root netem delay 100ms
模拟 1% 丢包率:tc qdisc add dev eth0 root netem loss 1%
对比结果数据如下:

图 3 不同丢包率和网络延迟下 TCP 协议、ENET、优化后 ENET 的平均响应时间对比

图 4 不同丢包率和网络延迟下 TCP 协议、ENET、优化后 ENET 的超时响应比例对比
从图中可见,在平均响应方面,TCP 协议的劣势不明显,在延迟为 30ms,丢包率为 1% 时,改进后的 ENET 平均 RTT 为 69ms, 原始 ENET 平均 RTT 为 67ms, TCP 平均 RTT 为 67ms;但是从响应时间超过 300ms 的比例看,在延迟为 30ms,丢包率为 1% 时,改进后的 ENET RTT 超过 300ms 的包为 0,而 TCP RTT 超过 300ms 的比例则超过了 2%,如果是在游戏中,这个表现已经能明显影响游戏体验了。结果表明,TCP 在网络稍不稳定的情况下就已经有比较大的问题了,改进后的 ENET 有明显优势。
总结
测试结果符合预期,在实时性方面,TCP 协议的网络抗性欠佳,对 MOBA 类或其他实时性要求较高的游戏,我们不建议使用 TCP 作为协议载体。事实上,王者荣耀,乱斗西游的通信协议也确实是基于 UDP 封装的,别问我是怎么知道的。
后话
对于开发人员来说,优化协议和同步算法是在已有网络环境下提升用户体验的可用方法,也是较平民化的方法,在网络抖动有限、丢包并不频繁、网络环境不至于太差的情况下,的确能有效提高游戏体验;然而这种方法也存在局限性,在网络环境超出可控范围,如在地铁上、商场里等人潮拥挤、存在网络热点,延迟或丢包率极高的环境中,还是无法解决问题,所谓“巧妇难为无米之炊”,再牛 X 的协议和算法,也无法点石成金,要从根本上解决问题,最终还是要回到网络质量上。
此文已由作者授权腾讯云 + 社区在各渠道发布
获取更多新鲜技术干货,可以关注我们腾讯云技术社区 - 云加社区官方号及知乎机构号 v

退出移动版