本文參考並引用了部分騰訊遊戲學院的相關技術文章內容,感謝原做者的分享。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)