以网游服务端的网络接入层设计为例,理解实时通信的技术挑战

前言

以现在主流的即时通讯应用形态来讲,一个完整的即时通讯IM应用其实是即时通信(英文简写:IM=Instant messaging)和实时通信(英文简写:RTC=Real-time communication)2种技术组合在一起的一整套网络通信系统。之所以以IM这个简写代称整个即时通讯软件,其实是历史原因了(因为早期的诸如ICQ这样的即时通讯工具,也就是文字聊天,并没有加入实时音视频这样的实时通信技术),对这个话题有兴趣的可以到网上查一查IM的发展历史。

以微信、QQ这样的完整即时通讯应用来说,回归到工具的本质,它主要包含了两种应用和技术:

  • 1)广义的文字聊天:也就是我最常理解的各种聊天消息的传递,这部分的技术实现就是众所周之的IM通信(即Instant messaging);

  • 2)实时音视频聊天:包括语音电话、视频聊天,这部分的技术实现,从网络通信的角度讲,就是实时通信(即Real-time communication)。

我们回忆一下:早几年前市面上主流的移动端IM——比如微信、QQ、以及现在满屏广告的网易易信、半死不活的小米米聊、已经入土的阿里来往、打擦边球的陌陌等,基本都没有或者很晚才加入实时音视频聊天功能(我们抛开技术因素之外的原因不议),原因不是不想做,而是实时音视频这种实时通信技术确实是有相当的门槛,并不容易做。

所以:对于即时通讯网社区内众多的IM应用开发者来说,实时通信技术如此重要,深入研究和理解实时通信技术的原理、技术实践,对于自已IM产品的开发来说,都是大有裨益的。

本文将尝试从开发者角度:梳理开发网游服务端的网络接入层的过程中面临的各种技术挑战,并针对性地提供相应的实时通信网络接入层解决思路,希望对于即时通讯应用的开发者来说,可以从中得到些许启发。

主流网游的网络通信架构原理

维基百科关于网络游戏的定义:

即通过计算机网络,将专用服务器和用户的客户端设备(手机、PC、游戏主机等)相连,让多名玩家同时联机进行游戏的娱乐形式。

由此可知网络游戏涉及三个角色:

  • 1)客户端;

  • 2)网络;

  • 3)服务器。

从网络架构上来讲,网游可分为:

  • 1)C/S 架构:这个最好理解;

  • 2)P2P架构:特指客户端间直连通信;

  • 3)C/M架构:在实际开发中这是一种C/S和P2P架构的混合体。

典型的网络架构如下图所示:

P2P架构不在本文讨论范围。

C/M架构和C/S架构相似,跟经典的LAMP网站架构类似,一般C/S架构的游戏后台也可划分为如下三层:

  • 1)网络接入层;

  • 2)游戏逻辑层;

  • 3) 数据存储层。

一般C/S架构的游戏后台分层,如下图所示:

网络接入、游戏逻辑、数据存储层各自所面临的问题域及对应技术栈都大为不同,做此划分不仅有助于模块解耦、技术分工、组件复用,也可方便服务的运维部署。本文要讨论的就是这个网络接入层。

题外话:该如何理解C/M架构?

可能有人对上节中的C/M架构有疑问,在网游中这个架构到底是怎么用的?

其实,网络游戏中是通过同步机制来保证各个客户端游戏世界的一致性。

主流的网游数据同步机制有两种:

  • 1)状态同步:即由客户端负责将玩家的操作发往中心节点 (服务器或master客户端),由中心节点来负责游戏逻辑计算并将计算结果广播给客户端,再由客户端负责渲染游戏结果

  • 2)帧同步:帧同步的理论基础是游戏逻辑由操作指令驱动,只要操作序列一致,那么游戏结果就应该一致。

也就是说,不管采用哪种数据同步机制,其实都是应用的C/M架构(即Client/Master架构)。

网络接入层的作用

网络接入层的主要任务是:

  • 1)建立客户端和后台服务以及客户端之间的信道,;

  • 2)接收来自客户端大量并发请求。

考核该层的主要性能指标是:

  • 1)高吞吐;

  • 2)低延迟。

因而网络接入层开发考验的是开发者高性能网络编程的功底,即解决C10K甚至C10M的能力。

网络接入层的通信协议选择

根据OSI的七层网络参考模型,我们可将网游网络也做如下7层划分:

其中4层以下都由操作系统来负责,开发者无需为此操心,在实际的开发过程中开发者首要面临的问题便是传输层是采用TCP还是UDP,下表简要对比了两者的优劣。 综合两者优劣,简单来说除非对延迟有极致要求(例如FPS、MOBA类游戏)需采用UDP外,TCP可应对大部分游戏。

在实际游戏开发中不管是采用TCP还是UDP方式,都较少利用通过Socket编程方式直接进行,一来因为开发工作量大,质量性能难以保证;二来平台兼容性不好(比如H5并没有提供socket编程能力),而是基于更上层的通讯协议比如基于TCP的HTTP、Websocket协议,GRPC,以及基于UDP实现的QUIC,WebRTC协议等。

TCP、UDP协议的简要对比:

​值得注意的是基于安全性考虑,浏览器标准未提供UDP收发能力,QUIC协议也只在chrome得到了支持,WebRTC也还不是浏览器事实标准且协议初始目的是用于实现点对点的音视频通信,协议内容过于庞杂不容易提炼应用于游戏开发中,因而现阶段H5游戏还只能采用HTTP或Websocket方式通讯。

另外 ,通讯协议确定后,随后要考虑的便是游戏对象的序列化,序列化主要有基于文本、基于二进制两种,其优劣如下表所示。在开发过程中一般会先采用文本序列化方式,便于前后端开发联调,在游戏正式上线前切换至二进制序列化方式以减少传输流量、提升编解码效率。

游戏对象的主要序列化方式:

至于数据安全性问题,为了保护敏感数据安全开发者可以选择安全的https或WSS通讯协议,而对于直接基于TCP协议通讯,可采用先用RSA协商加密秘钥,然后使用对称加密方式将数据加密后发送。

通过以上分析,对于游戏协议类型的选择我们给出有以下准则:

  • 1)弱联网类游戏:诸如休闲、卡牌类游戏可直接HTTP协议,对安全性有要求的话就使用HTTPS

  • 2)实时性,交互性要求较高:这类游戏一般需要保持长连接,优先选择标准的ws协议(同时使用二进制序列化方式,如Protobuf),如考虑安全性可使用wss协议。而对于提供socket接口的native平台也可使用TCP协议,同时对数据做对称加密增强安全性;

  • 3)实时性要求极高:不仅需要和服务器保持长连接,且延迟和网络抖动都要求极高(如FPS,赛车类游戏),可使用基于UDP的实现流传输协议如QUIC,KCP等。

后台 扣1,领取上方资料

7、网络接入层的并发模型

为了处理来自客户端的并发请求,服务端有4种常见的并发模型。

7.1)进程:

进程是最早采用的并发模型,进程作为操作资源分配、调度的单位,拥有独立的运行空间。进程并发模型中每个请求由独立的进程来处理,进程一次只能处理一个请求,该模型最大的优点就是简单。如果处理请求的进程由于系统调用而阻塞或进程的时间片用完,抢占式的进程调度器就会暂停旧进程执行,调度执行新的进程,这个过程涉及大开销的上下文切换,进程并发模型的缺点是比较低效。最典型的采用进程模型的服务有Apache。

7.2)线程:

线程并发模型是进程模型的改进,线程从属于进程,是系统更小粒度的执行调度单元。不同请求可由进程内多个并发执行的线程来处理,这些线程由操作系统内核自动调度。线程相对进程的主要优势在于,调度上下文切换开销更小,但由于多个线程共享地址空间,需要额外的线程间互斥、同步机制来保证程序性正确性。典型的采用线程模型的服务有Tomcat。

7.3)IO多路复用:

利用操作系统提供的epoll等IO多路复用机制,能同时监控多个连接上读、写事件, IO多路复用也称事件驱动模型,网络程序执行逻辑可抽象为事件驱动的状态机。 IO多路复用避免了读写阻塞,减少了上下文切换,提升了CPU利用率和系统吞吐率。但IO多路复用它将原本“同步”、线性的处理逻辑变成事件驱动的状态机,处理逻辑分散于大量的事件回调函数。这种异步、非线性的模型,极大地增加了编程难度,如nodeJs的常见的回调地狱问题。典型的采用IO复用模型的服务有Nginx、Netty。

7.4)协程:

协程也称为轻量级线程,是一种协同的、非抢占式的多任务并发模型。 协程运行在用户空间,当遇到阻塞或特定入口时,通过显式调用切换方法主动让出CPU,由任务调度器选取另一个协程执行。

协程切换只是简单地改变执行函数栈,不涉及内核态与用户态转化,也涉及上下文切换,开销远小于进程/线程切换。协程的概念虽早已提出,随着近些年年越来越多的语言(go、 Haskell)内置对协程支持才被开发者所熟知,协程极大的优化了开发者编程体验,在同步、顺序编程风格能快速实现程序逻辑,还拥有IO多路复用异步编程的性能。典型的采用协程模型的服务有openresty(Lua), gevent(Python), golang。

7.5)小结:

以上总结了目前4种常用的并发模型,它们在工作原理、运行效率、编程难度等方面有显著区别,各自有适用场景,在实际使用时应该根据需求仔细评估。在实际开发过程中如果没有可复用的现成网络组件或历史包袱我们建议使用协程并发模式开发网络接入层服务。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值