• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            Fork me on GitHub
            隨筆 - 215  文章 - 13  trackbacks - 0
            <2025年7月>
            293012345
            6789101112
            13141516171819
            20212223242526
            272829303112
            3456789


            專注即時(shí)通訊及網(wǎng)游服務(wù)端編程
            ------------------------------------
            Openresty 官方模塊
            Openresty 標(biāo)準(zhǔn)模塊(Opm)
            Openresty 三方模塊
            ------------------------------------
            本博收藏大部分文章為轉(zhuǎn)載,并在文章開頭給出了原文出處,如有再轉(zhuǎn),敬請保留相關(guān)信息,這是大家對原創(chuàng)作者勞動(dòng)成果的自覺尊重!!如為您帶來不便,請于本博下留言,謝謝配合。

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            相冊

            Awesome

            Blog

            Book

            GitHub

            Link

            搜索

            •  

            積分與排名

            • 積分 - 216832
            • 排名 - 118

            最新評論

            閱讀排行榜

            http://www.infoq.com/cn/articles/game-server-development-2

            在上一篇文章中, 我們介紹了游戲服務(wù)器的基本架構(gòu)、相關(guān)框架和Node.js開發(fā)游戲服務(wù)器的優(yōu)勢。本文我們將通過聊天服務(wù)器的設(shè)計(jì)與開發(fā),來更深入地理解pomelo開發(fā)應(yīng)用的基本流程、開發(fā)思路與相關(guān)的概念。本文并不是開發(fā)聊天服務(wù)器的tutorial,如果需要tutorial和源碼可以看文章最后的參考資料。

            為什么是聊天服務(wù)器?

            我們目標(biāo)是搭建游戲服務(wù)器,為什么從聊天開始呢?

            聊天可認(rèn)為是簡化的實(shí)時(shí)游戲,它與游戲服務(wù)器有著很多共通之處,如實(shí)時(shí)性、頻道、廣播等。由于游戲在場景管理、客戶端動(dòng)畫等方面有一定的復(fù)雜性,并不適合作為pomelo的入門應(yīng)用。聊天應(yīng)用通常是Node.js入門接觸的第一個(gè)應(yīng)用,因此更適合做入門教程。

            Pomelo是游戲服務(wù)器框架,本質(zhì)上也是高實(shí)時(shí)、可擴(kuò)展、多進(jìn)程的應(yīng)用框架。除了在library中有一部分游戲?qū)S玫膸欤溆嗖糠挚蚣芡耆捎糜陂_發(fā)高實(shí)時(shí)web應(yīng)用。而且與現(xiàn)在有的Node.js高實(shí)時(shí)應(yīng)用框架如derby、socketstream、meteor等比起來有更好的可伸縮性。

            相關(guān)贊助商

            QCon北京2016大會(huì),4月21-23日,北京·國際會(huì)議中心,精彩內(nèi)容邀您參與!

            對于大多數(shù)開發(fā)者而言,Node.js的入門應(yīng)用都是一個(gè)基于socket.io開發(fā)的普通聊天室, 由于它是基于單進(jìn)程的Node.js開發(fā)的, 在可擴(kuò)展性上打了一定折扣。例如要擴(kuò)展到類似irc那樣的多頻道聊天室, 頻道數(shù)量的增多必然會(huì)導(dǎo)致單進(jìn)程的Node.js支撐不住。

            而基于pomelo框架開發(fā)的聊天應(yīng)用天生就是多進(jìn)程的,可以非常容易地?cái)U(kuò)展服務(wù)器類型和數(shù)量。

            從單進(jìn)程到多進(jìn)程,從socket.io到pomelo

            一個(gè)基于socket.io的原生聊天室應(yīng)用架構(gòu), 以uberchat為例。

            它的應(yīng)用架構(gòu)如下圖所示:

            服務(wù)端由單個(gè)Node.js進(jìn)程組成的chat server來接收websocket請求。

            它有以下缺點(diǎn):

            1. 可擴(kuò)展性差:只支持單進(jìn)程的Node.js, 無法根據(jù)room/channel分區(qū), 也無法將廣播的壓力與處理邏輯的壓力分開。

            2. 代碼量大:基于socket.io做了簡單封裝,服務(wù)端就寫了約430行代碼。

            用pomelo來寫這個(gè)框架可完全克服以上缺點(diǎn),并且代碼量只要區(qū)區(qū)100多行。

            我們要搭建的pomelo聊天室具有如下的運(yùn)行架構(gòu):

            在這個(gè)架構(gòu)里, 前端服務(wù)器也就是connector專門負(fù)責(zé)承載連接, 后端的聊天服務(wù)器則是處理具體邏輯的地方。 這樣擴(kuò)展的運(yùn)行架構(gòu)具有如下優(yōu)勢: * 負(fù)載分離:這種架構(gòu)將承載連接的邏輯與后端的業(yè)務(wù)處理邏輯完全分離,這樣做是非常必要的, 尤其是廣播密集型應(yīng)用(例如游戲和聊天)。密集的廣播與網(wǎng)絡(luò)通訊會(huì)占掉大量的資源,經(jīng)過分離后業(yè)務(wù)邏輯的處理能力就不再受廣播的影響。

            • 切換簡便:因?yàn)橛辛饲啊⒑蠖藘蓪拥募軜?gòu),用戶可以任意切換頻道或房間都不需要重連前端的websocket。

            • 擴(kuò)展性好:用戶數(shù)的擴(kuò)展可以通過增加connector進(jìn)程的數(shù)量來支撐。頻道的擴(kuò)展可以通過哈希等算法負(fù)載均衡到多臺(tái)聊天服務(wù)器上。理論上這個(gè)架構(gòu)可以實(shí)現(xiàn)頻道和用戶的無限擴(kuò)展。

            聊天服務(wù)器開發(fā)架構(gòu)

            game server與web server

            聊天服務(wù)器項(xiàng)目中分生成了game-server目錄、web-server目錄與shared目錄,如下圖所示:

            這樣也將應(yīng)用天然地隔離成了兩個(gè),game server與web server。

            • Game server, 即游戲服務(wù)器,所有的游戲服務(wù)器邏輯都在里實(shí)現(xiàn)。客戶端通過websocket(0.3版會(huì)支持tcp的socket)連到game server。game-server/app.js是游戲服務(wù)器的運(yùn)行入口。
            • Web server,即web服務(wù)器, 也可以認(rèn)為是游戲服務(wù)器的一個(gè)web客戶端, 所有客戶端的js代碼,web端的html、css資源都存放在這里,web服務(wù)端的用戶登錄、認(rèn)證等功能也在這里實(shí)現(xiàn)。pomelo也提供了其它客戶端,包括ios、android、unity3D等。
            • Shared目錄,假如客戶端是web,由于服務(wù)端和客戶端都是javascript寫的,這時(shí)Node.js的代碼重用優(yōu)勢就體現(xiàn)出來了。shared目錄下可以存放客戶端、服務(wù)端共用的常量、算法。真正做到一遍代碼, 前后端共用。

            服務(wù)器定義與應(yīng)用目錄

            Game server才是游戲服務(wù)器的真正入口,游戲邏輯都在里, 我們簡單看一下game-server的目錄結(jié)構(gòu),如下圖所示:

            servers目錄下所有子目錄定義了各種類型的服務(wù)器,而每個(gè)servers目錄下基本都包含了handler和remote兩個(gè)目錄。 這是pomelo的創(chuàng)新之處,用極簡的配置實(shí)現(xiàn)游戲服務(wù)器的定義,后文會(huì)解釋handler和remote。

            通過pomelo,游戲開發(fā)者可以自由地定義自己的服務(wù)器類型,分配和管理進(jìn)程資源。在pomelo中,根據(jù)服務(wù)器的職責(zé)不同,服務(wù)器主要分為前端服務(wù)器(frontend)和后端服務(wù)器(backend)兩大類。其中,前端服務(wù)器負(fù)責(zé)承載客戶端的連接和維護(hù)session信息,所有服務(wù)器與客戶端的消息都會(huì)經(jīng)過前端服務(wù)器;后端服務(wù)器負(fù)責(zé)接收前端服務(wù)器分發(fā)過來的請求,實(shí)現(xiàn)具體的游戲邏輯,并把消息回推給前端服務(wù)器,最后發(fā)送給客戶端。如下圖所示:

            動(dòng)態(tài)語言的面向?qū)ο笥袀€(gè)基本概念叫鴨子類型。在pomelo中,服務(wù)器的抽象也同樣可以比喻為鴨子,服務(wù)器的對外接口只有兩類, 一類是接收客戶端的請求, 叫做handler, 一類是接收RPC請求, 叫做remote, handler和remote的行為決定了服務(wù)器長什么樣子。 因此開發(fā)者只需要定義好handler和remote兩類的行為, 就可以確定這個(gè)服務(wù)器的類型。 例如chat服務(wù)器目前的行為只有兩類,分別是定義在handler目錄中的chatHandler.js,和定義在remote目錄中的chatRemote.js。只要定義好這兩個(gè)類的方法,聊天服務(wù)器的對外接口就確定了。

            搭建聊天服務(wù)器

            準(zhǔn)備知識

            pomelo的客戶端服務(wù)器通訊

            pomelo的客戶端和服務(wù)器之間的通訊可以分為三種:

            • request-response

              pomelo中最常用的就是request-response模式,客戶端發(fā)送請求,服務(wù)器異步響應(yīng)。客戶端的請求發(fā)送形式類似ajax類似:

              ``` pomelo.request(url, msg, function(data){}); ``` 

              第一個(gè)參數(shù)為請求地址,完整的請求地址主要包括三個(gè)部分:服務(wù)器類型、服務(wù)端相應(yīng)的文件名及對應(yīng)的方法名。第二個(gè)參數(shù)是消息體,消息體為json格式,第三個(gè)參數(shù)是回調(diào)函數(shù),請求的響應(yīng)將會(huì)把結(jié)果置入這個(gè)回調(diào)函數(shù)中返回給客戶端。

            • notify

              notify與request—response類似,唯一區(qū)別是客戶端只負(fù)責(zé)發(fā)送消息到服務(wù)器,客戶端不接收服務(wù)器的消息響應(yīng)。

              ``` pomelo.notify(url, msg); ``` 
            • push

              push則是服務(wù)器主動(dòng)向客戶端進(jìn)行消息推送,客戶端根據(jù)路由信息進(jìn)行消息區(qū)分,轉(zhuǎn)發(fā)到后。通常游戲服務(wù)器都會(huì)發(fā)送大量的這類廣播。

              ``` pomelo.on(route, function(data){}); ``` 

            以上是javascript的api, 其它客戶端的API基本與這個(gè)類型。由于API與ajax極其類似,所有web應(yīng)用的開發(fā)者對此都不陌生。

            session介紹

            與web服務(wù)器類似,session是游戲服務(wù)器存放用戶會(huì)話的抽象。但與web不同,游戲服務(wù)器的session是基于長連接的, 一旦建立就一直保持。這反而比web中的session更直接,也更簡單。 由于長連接的session不會(huì)web應(yīng)用一樣由于連接斷開重連帶來session復(fù)制之類的問題,簡單地將session保存在前端服務(wù)器的內(nèi)存中是明智的選擇。

            在pomelo中session也是key/value對象,其主要作用是維護(hù)當(dāng)前用戶信息,例如:用戶的id,所連接的前端服務(wù)器id等。session由前端服務(wù)器維護(hù),前端服務(wù)器在分發(fā)請求給后端服務(wù)器時(shí),會(huì)復(fù)制session并連同請求一起發(fā)送。任何直接在session上的修改,只對本服務(wù)器進(jìn)程生效,并不會(huì)影響到用戶的全局狀態(tài)信息。如需修改全局session里的狀態(tài)信息,需要調(diào)用前端服務(wù)器提供的RPC服務(wù)。

            channel與廣播

            廣播在游戲中是極其重要的,幾乎大部分的消息都需要通過廣播推送到客戶端,再由客戶端播放接收的消息。而channel則是服務(wù)器端向客戶端進(jìn)行消息廣播的通道。 可以把channel看成一個(gè)用戶id的容器.把用戶id加入到channel中成為當(dāng)中的一個(gè)成員,之后向channel推送消息,則該channel中所有的成員都會(huì)收到消息。channel只適用于服務(wù)器進(jìn)程本地,即在服務(wù)器進(jìn)程A創(chuàng)建的channel和在服務(wù)器進(jìn)程B創(chuàng)建的channel是兩個(gè)不同的channel,相互不影響。

            服務(wù)器之間RPC通訊

            從之前的文章可以了解到,在pomelo中,游戲服務(wù)器其實(shí)是一個(gè)多進(jìn)程相互協(xié)作的環(huán)境。各個(gè)進(jìn)程之間通信,主要是通過底層統(tǒng)一的RPC框架來實(shí)現(xiàn),服務(wù)器間的RPC調(diào)用也實(shí)現(xiàn)了零配置。具體RPC調(diào)用的代碼如下:

            ```javascript app.rpc.chat.chatRemote.add(session, uid, app.get ('serverId'), function(data){}); ``` 

            其中app是pomelo的應(yīng)用對象,app.rpc表明了是前后臺(tái)服務(wù)器的Remote rpc調(diào)用,后面的參數(shù)分別代表服務(wù)器的名稱、對應(yīng)的文件名稱及方法名。為了實(shí)現(xiàn)這個(gè)rpc調(diào)用,則只需要在對應(yīng)的chat/remote/中新建文件chatRemote.js,并實(shí)現(xiàn)add方法。

            聊天室流程概述

            下圖列出了聊天室進(jìn)行聊天的完整流程:

            通過以上流程, 我們可以看到pomelo的基本請求流程和用法。本文不是聊天室的tutorial,因此下面列出的代碼不是完整的,而是用極簡的代碼來說明pomelo的使用流程和api。

            進(jìn)入聊天室

            客戶端向前端服務(wù)器發(fā)起登錄請求:

            ```javascript     pomelo.request('connector.entryHandler.enter',      {user:userInfo}, function(){}); ``` 

            用戶進(jìn)入聊天室后,服務(wù)器端首先需要完成用戶的session注冊同時(shí)綁定用戶離開事件:

            ```javascript session.bind(uid); session.on('closed', onUserLeave.bind(null, app)); ``` 

            另外,服務(wù)器端需要通過調(diào)用rpc方法將用戶加入到相應(yīng)的channel中;同時(shí)在rpc方法中,服務(wù)器端需要將該用戶的上線消息廣播給其他用戶,最后服務(wù)器端向客戶端返回當(dāng)前channel中的用戶列表信息。

            ```javascript app.rpc.chat.chatRemote.add(session, uid,  serverId,function(){}); ``` 

            發(fā)起聊天

            客戶端向服務(wù)端發(fā)起聊天請求,請求消息包括聊天內(nèi)容,發(fā)送者和發(fā)送目標(biāo)信息。消息的接收者可以聊天室里所有的用戶,也可以是某一特定用戶。

            服務(wù)器端根據(jù)客戶端的發(fā)送的請求,進(jìn)行不同形式的消息廣播。如果發(fā)送目標(biāo)是所有用戶,服務(wù)器端首先會(huì)選擇channel中的所有用戶,然后向channel發(fā)送消息,最后前端服務(wù)器就會(huì)將消息分別發(fā)送給channel中取到的用戶;如果發(fā)送目標(biāo)只是某一特定用戶,發(fā)送過程和之前完全一樣,只是服務(wù)器端首先從channel中選擇的只是一個(gè)用戶,而不是所有用戶。

            ```javascript     if(msg.target == '*')          channel.pushMessage(param);     else         channelService.pushMessageByUids(param,         [{uid:uid, sid:sid}]); ``` 

            接收聊天消息

            客戶端接收廣播消息,并將消息并顯示即可。

            ```javascript     pomelo.on('onChat', function() {         addMessage(data.from, data.target, data.msg);             $("#chatHistory").show();     }); ``` 

            退出聊天室

            用戶在退出聊天室時(shí),必須完成一些清理工作。在session斷開連接時(shí),通過rpc調(diào)用將用戶從channel中移除。在用戶退出前,還需要將自己下線的消息廣播給所有其他用戶。

            ```javascript     app.rpc.chat.chatRemote.kick(session, uid, serverId,      channelName, null); ``` 

            聊天服務(wù)器的可伸縮性與擴(kuò)展討論

            上一講已經(jīng)談到pomelo在提供了一個(gè)高可伸縮性的運(yùn)行架構(gòu),對于聊天服務(wù)器同樣如此。如果想從單頻道聊天室擴(kuò)展到多頻道聊天室,增加的代碼幾乎為零。大部分工作只是在進(jìn)行服務(wù)器和路由的配置。對于服務(wù)器配置只需要修改json配置文件即可,而對于路由配置只需要增加一個(gè)路由算法即可。在pomelo中,開發(fā)者可以自己配置客戶端到服務(wù)器的路由規(guī)則,這樣會(huì)使得游戲開發(fā)更加靈活。

            我們來看一下配置json文件對服務(wù)器運(yùn)行架構(gòu)的影響:

            • 最簡服務(wù)器與運(yùn)行架構(gòu):

            • 擴(kuò)展后的服務(wù)器與運(yùn)行架構(gòu):

            另外,在0.3版本的pomelo中增加了動(dòng)態(tài)增刪服務(wù)器的功能,開發(fā)者可以在不停服務(wù)的情況下根據(jù)當(dāng)前應(yīng)用運(yùn)行的負(fù)載情況添加新的服務(wù)器或者停止閑置的服務(wù)器,這樣可以讓服務(wù)器資源得到更充分的利用。

            總結(jié)

            本文通過聊天服務(wù)器的搭建過程,分析了pomelo開發(fā)應(yīng)用的基本流程,基本架構(gòu)與相關(guān)概念。有了這些知識我們可以輕松地使用pomelo搭建高實(shí)時(shí)應(yīng)用了。 在后文中我們將分析更復(fù)雜的游戲案例,并且會(huì)對架構(gòu)中的一些實(shí)現(xiàn)深入剖析。

            相關(guān)資源:

            posted on 2016-03-14 09:13 思月行云 閱讀(1792) 評論(0)  編輯 收藏 引用 所屬分類: Node.js
            狠狠色综合网站久久久久久久高清| 国产成人久久精品激情| 久久无码一区二区三区少妇| 久久99亚洲综合精品首页| 久久精品人妻中文系列| 国产成人精品综合久久久| 久久毛片一区二区| 久久狠狠高潮亚洲精品| 日本福利片国产午夜久久| 久久人人爽人人爽人人片av高请| 久久久午夜精品福利内容| 999久久久免费国产精品播放| 久久夜色精品国产噜噜麻豆| 国产一久久香蕉国产线看观看| 久久久久久狠狠丁香| 久久一区二区三区99| 日本三级久久网| 91久久精一区二区三区大全| 一本久久精品一区二区| 久久青青草原国产精品免费| 大伊人青草狠狠久久| 久久w5ww成w人免费| 久久国产成人| 亚洲精品无码久久久久久| 精品久久久久久久久中文字幕| 久久国产热精品波多野结衣AV| 精品久久久久久国产牛牛app| 久久精品国产亚洲av水果派| 久久天天躁夜夜躁狠狠| 中文字幕亚洲综合久久| 久久久久亚洲AV无码去区首| 99久久免费国产特黄| 亚洲Av无码国产情品久久| 久久国产成人| 久久精品国产亚洲av日韩| 一级做a爰片久久毛片人呢| 久久久久久久91精品免费观看| 久久91精品国产91久久小草| 久久夜色精品国产噜噜麻豆| 久久久免费精品re6| 区亚洲欧美一级久久精品亚洲精品成人网久久久久 |