本文参考并引用了部分腾讯游戏学院的相关技术文章内容,感谢原做者的分享。php
以如今主流的即时通信应用形态来说,一个完整的即时通信IM应用实际上是即时通讯(英文简写:IM=Instant messaging)和实时通讯(英文简写:RTC=Real-time communication)2种技术组合在一块儿的一整套网络通讯系统。之因此以IM这个简写代称整个即时通信软件,实际上是历史缘由了(由于早期的诸如ICQ这样的即时通信工具,也就是文字聊天,并无加入实时音视频这样的实时通讯技术),对这个话题有兴趣的能够到网上查一查IM的发展历史。html
以微信、QQ这样的完整即时通信应用来讲,回归到工具的本质,它主要包含了两种应用和技术:node
1)广义的文字聊天:也就是我最常理解的各类聊天消息的传递,这部分的技术实现就是众所周之的IM通讯(即Instant messaging);golang
2)实时音视频聊天:包括语音电话、视频聊天,这部分的技术实现,从网络通讯的角度讲,就是实时通讯(即Real-time communication)。chrome
咱们回忆一下:早几年前市面上主流的移动端IM——好比微信、QQ、以及如今满屏广告的网易易信、半死不活的小米米聊、已经入土的阿里来往、打擦边球的陌陌等,基本都没有或者很晚才加入实时音视频聊天功能(咱们抛开技术因素以外的缘由不议),缘由不是不想作,而是实时音视频这种实时通讯技术确实是有至关的门槛,并不容易作。编程
因此:对于即时通信网社区内众多的IM应用开发者来讲,实时通讯技术如此重要,深刻研究和理解实时通讯技术的原理、技术实践,对于自已IM产品的开发来讲,都是大有裨益的。小程序
本文将尝试从开发者角度:梳理开发网游服务端的网络接入层的过程当中面临的各类技术挑战,并针对性地提供相应的实时通讯网络接入层解决思路,但愿对于即时通信应用的开发者来讲,能够从中获得些许启发。后端
学习交流:微信小程序
- 即时通信开发交流3群:185926912 [推荐]浏览器
- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》
(本文同步发布于:http://www.52im.net/thread-1915-1-1.html)
《高性能网络编程(一):单台服务器并发TCP链接数到底能够有多少》
《高性能网络编程(二):上一个10年,著名的C10K并发链接问题》
《高性能网络编程(三):下一个10年,是时候考虑C10M并发问题了》
《高性能网络编程(四):从C10K到C10M高性能网络应用的理论探索》
《鲜为人知的网络编程(七):如何让不可靠的UDP变的可靠?》
《网络编程懒人入门(五):快速理解为何说UDP有时比TCP更有优点》
《技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解》
《脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手》
《脑残式网络编程入门(二):咱们在读写Socket时,究竟在读写什么?》
维基百科关于网络游戏的定义:
即经过计算机网络,将专用服务器和用户的客户端设备(手机、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架构有疑问,在网游中这个架构究竟是怎么用的?
其实,网络游戏中是经过同步机制来保证各个客户端游戏世界的一致性。
主流的网游数据同步机制有两种:
1)状态同步:即由客户端负责将玩家的操做发往中心节点 (服务器或master客户端),由中心节点来负责游戏逻辑计算并将计算结果广播给客户端,再由客户端负责渲染游戏结果
2)帧同步:帧同步的理论基础是游戏逻辑由操做指令驱动,只要操做序列一致,那么游戏结果就应该一致。
也就是说,无论采用哪一种数据同步机制,其实都是应用的C/M架构(即Client/Master架构)。
网络接入层的主要任务是:
1)创建客户端和后台服务以及客户端之间的信道,;
2)接收来自客户端大量并发请求。
考核该层的主要性能指标是:
1)高吞吐;
2)低延迟。
于是网络接入层开发考验的是开发者高性能网络编程的功底,即解决C10K甚至C10M的能力。
题外话:有关高性能网络编程的C10K、C10M话题,请详细阅读如下文章
《高性能网络编程(一):单台服务器并发TCP链接数到底能够有多少》
《高性能网络编程(二):上一个10年,著名的C10K并发链接问题》
根据OSI的七层网络参考模型,咱们可将网游网络也作以下7层划分:
其中4层如下都由操做系统来负责,开发者无需为此操心,在实际的开发过程当中开发者首要面临的问题即是传输层是采用TCP仍是UDP,下表简要对比了二者的优劣。 综合二者优劣,简单来讲除非对延迟有极致要求(例如FPS、MOBA类游戏)需采用UDP外,TCP可应对大部分游戏。
在实际游戏开发中无论是采用TCP仍是UDP方式,都较少利用经过Socket编程方式直接进行,一来由于开发工做量大,质量性能难以保证;二来平台兼容性很差(好比H5并无提供socket编程能力),而是基于更上层的通信协议好比基于TCP的HTTP、Websocket协议,GRPC,以及基于UDP实现的QUIC,WebRTC协议等。
TCP、UDP协议的简要对比:
有关TCP、UDP协议的详细对比文章,您可简读一下资料:
值得注意的是基于安全性考虑,浏览器标准未提供UDP收发能力,QUIC协议也只在chrome获得了支持,WebRTC也还不是浏览器事实标准且协议初始目的是用于实现点对点的音视频通讯,协议内容过于庞杂不容易提炼应用于游戏开发中,于是现阶段H5游戏还只能采用HTTP或Websocket方式通信。
知识点扫盲:
1)关于QUIC协议:《技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解》;
2)关于WebRTC:《开源实时音视频技术WebRTC的现状》、《简述开源实时音视频技术WebRTC的优缺点》、《访谈WebRTC标准之父:WebRTC的过去、如今和将来》;
3)关于Websocket:《新手入门贴:史上最全Web端即时通信技术原理详解》、《Web端即时通信技术盘点:短轮询、Comet、Websocket、SSE》、《新手快速入门:WebSocket简明教程》、《WebSocket详解(一):初步认识WebSocket技术》。
另外 ,通信协议肯定后,随后要考虑的即是游戏对象的序列化,序列化主要有基于文本、基于二进制两种,其优劣以下表所示。在开发过程当中通常会先采用文本序列化方式,便于先后端开发联调,在游戏正式上线前切换至二进制序列化方式以减小传输流量、提高编解码效率。
游戏对象的主要序列化方式:
关于Protobuf的详细资料,请见:
《强列建议将Protobuf做为你的即时通信应用数据传输格式》
至于数据安全性问题,为了保护敏感数据安全开发者能够选择安全的https或WSS通信协议,而对于直接基于TCP协议通信,可采用先用RSA协商加密秘钥,而后使用对称加密方式将数据加密后发送。
经过以上分析,对于游戏协议类型的选择咱们给出有如下准则:
1)弱联网类游戏:诸如休闲、卡牌类游戏可直接HTTP协议,对安全性有要求的话就使用HTTPS;
2)实时性,交互性要求较高:这类游戏通常须要保持长链接,优先选择标准的ws协议(同时使用二进制序列化方式,如Protobuf),如考虑安全性可以使用wss协议。而对于提供socket接口的native平台也可以使用TCP协议,同时对数据作对称加密加强安全性;
3)实时性要求极高:不只须要和服务器保持长链接,且延迟和网络抖动都要求极高(如FPS,赛车类游戏),可以使用基于UDP的实现流传输协议如QUIC,KCP等。
为了处理来自客户端的并发请求,服务端有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种经常使用的并发模型,它们在工做原理、运行效率、编程难度等方面有显著区别,各自有适用场景,在实际使用时应该根据需求仔细评估。在实际开发过程当中若是没有可复用的现成网络组件或历史包袱咱们建议使用协程并发模式开发网络接入层服务。
[1] 网络编程基础资料:
《技术往事:改变世界的TCP/IP协议(珍贵多图、手机慎点)》
《通俗易懂-深刻理解TCP协议(下):RTT、滑动窗口、拥塞处理》
《理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程》
《P2P技术详解(一):NAT详解——详细原理、P2P简介》
《P2P技术详解(二):P2P中的NAT穿越(打洞)方案详解》
《P2P技术详解(三):P2P技术之STUN、TURN、ICE详解》
《鲜为人知的网络编程(一):浅析TCP协议中的疑难杂症(上篇)》
《鲜为人知的网络编程(二):浅析TCP协议中的疑难杂症(下篇)》
《鲜为人知的网络编程(三):关闭TCP链接时为何会TIME_WAIT、CLOSE_WAIT》
《鲜为人知的网络编程(七):如何让不可靠的UDP变的可靠?》
《网络编程懒人入门(五):快速理解为何说UDP有时比TCP更有优点》
《网络编程懒人入门(六):史上最通俗的集线器、交换机、路由器功能原理入门》
《网络编程懒人入门(八):手把手教你写基于TCP的Socket长链接》
《现代移动端网络短链接的优化手段总结:请求速度、弱网适应、安全保障》
《移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”》
《移动端IM开发者必读(二):史上最全移动弱网络优化方法总结》
《从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路》
《脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手》
《脑残式网络编程入门(二):咱们在读写Socket时,究竟在读写什么?》
《脑残式网络编程入门(三):HTTP协议必知必会的一些知识》
《脑残式网络编程入门(四):快速理解HTTP/2的服务器推送(Server Push)》
《以网游服务端的网络接入层设计为例,理解实时通讯的技术挑战》
>> 更多同类文章 ……
[2] 有关网络通讯的格式、协议的选择:
《一个基于Protocol Buffer的Java代码演示》
《全方位评测:Protobuf性能到底有没有比JSON快5倍?》
《详解如何在NodeJS中使用Google的Protobuf》
>> 更多同类文章 ……
[3] 实时音视频开发的其它精华资料:
《即时通信音视频开发(五):认识主流视频编码技术H.264》
《即时通信音视频开发(九):实时语音通信的回音及回音消除概述》
《即时通信音视频开发(十):实时语音通信的回音消除技术详解》
《即时通信音视频开发(十一):实时语音通信丢包补偿技术详解》
《即时通信音视频开发(十三):实时视频编码H.264的特色与优点》
《即时通信音视频开发(十五):聊聊P2P与实时音视频的应用状况》
《即时通信音视频开发(十六):移动端实时音视频开发的几个建议》
《即时通信音视频开发(十七):视频编码H.26四、VP8的前世此生》
《首次披露:快手是如何作到百万观众同场看直播仍能秒开且不卡顿的?》
《腾讯音视频实验室:使用AI黑科技实现超低码率的高清实时视频聊天》
《七牛云技术分享:使用QUIC协议实现实时视频直播0卡顿!》
《实时视频直播客户端技术盘点:Native、HTML五、WebRTC、微信小程序》
(本文同步发布于:http://www.52im.net/thread-1915-1-1.html)