- 百萬(wàn)在線(xiàn):大型游戲服務(wù)端開(kāi)發(fā)
- 羅培羽
- 1839字
- 2021-09-17 17:04:58
3.3 搭架子:目錄結(jié)構(gòu)和配置
開(kāi)始編碼吧!既然這是個(gè)“大項(xiàng)目”,就要有大項(xiàng)目的樣子,就要有所規(guī)劃,下面先把項(xiàng)目的架子搭起來(lái)。
3.3.1 目錄結(jié)構(gòu)
建立如圖3-5所示的目錄結(jié)構(gòu),各個(gè)文件(夾)的作用如表3-3所示。建議把Skynet框架放到一個(gè)文件夾里,把所有自己編寫(xiě)的內(nèi)容都放到外層的文件夾里。筆者見(jiàn)過(guò)的不少實(shí)際項(xiàng)目都是使用的類(lèi)似結(jié)構(gòu)。
表3-3 各個(gè)文件(夾)的作用

service文件夾用于存放各種服務(wù)的代碼,如圖3-6所示。每個(gè)服務(wù)的代碼都放到一個(gè)以服務(wù)名稱(chēng)命名的文件夾里。按照3.2.1節(jié)的設(shè)計(jì),服務(wù)端會(huì)開(kāi)啟gateway、login、agent等多種服務(wù),我們光給每個(gè)服務(wù)建立對(duì)應(yīng)的文件夾。主服務(wù)是節(jié)點(diǎn)啟動(dòng)后第一個(gè)被加載的服務(wù),用于啟動(dòng)其他各個(gè)服務(wù),它比較特殊,我們不給它創(chuàng)建對(duì)應(yīng)的文件夾,而是為它創(chuàng)建一個(gè)Lua文件——main.lua。

圖3-5 游戲項(xiàng)目目錄結(jié)構(gòu)

圖3-6 service文件夾的內(nèi)容
3.3.2 配置文件
更改了目錄結(jié)構(gòu),需要重新編寫(xiě)Skynet的配置文件,讓Skynet可以加載項(xiàng)目代碼。在etc文件夾下新建文本文件config.node1和config.node2,它們代表各個(gè)節(jié)點(diǎn)的配置。config.node1中的代碼如代碼3-1所示,需注意標(biāo)注了底紋的部分。
代碼3-1 etc/config.node1
(資源:Chapter3/rill4)
--必須配置 thread = 8 --啟用多少個(gè)工作線(xiàn)程 cpath = "./skynet/cservice/?.so" --用C編寫(xiě)的服務(wù)模塊的位置 bootstrap = "snlua bootstrap" --啟動(dòng)的第一個(gè)服務(wù) --bootstrap配置項(xiàng) start = "main" --主服務(wù)入口 harbor = 0 --不使用主從節(jié)點(diǎn)模式 --lua配置項(xiàng) lualoader = "./skynet/lualib/loader.lua" luas ervice =.. "./skynet/service/?. lua;" lua_ path = .. "./skynet/lualib/?. lua;" .. "./skynet/lualib/?/init.lua" lua_cpath = .. "./skynet/luaclib/?.so" --后臺(tái)模式(必要時(shí)開(kāi)啟) --daemon = "./skynet.pid" --logger = "./userlog" --節(jié)點(diǎn) node = "node1"
這份配置與Skynet的默認(rèn)配置沒(méi)有太大區(qū)別,但有一些需要注意的地方,具體如下:
1)因?yàn)镾kynet引擎被放置到skynet文件夾下了,所以要重設(shè)cpath、lualoader、luaservice、lua_path、lua_cpath的路徑。
2)由于自定義服務(wù)位于service文件夾下,因此要修改luaservice配置項(xiàng),讓它搜索該文件夾。按照代碼3-1的設(shè)置,它會(huì)查找service/[服務(wù)名].lua或service/[服務(wù)名]/init.lua作為服務(wù)的啟動(dòng)文件。如果查找失敗,才去搜索Skynet提供的服務(wù)。
3)依據(jù)代碼中l(wèi)ua_path項(xiàng)的配置,當(dāng)程序需要加載Lua模塊時(shí),它會(huì)依次查找etc/[模塊名].lua、lualib/[模塊名].lua,再查找skynet提供的模塊。
4)自定義環(huán)境變量“node”,代表節(jié)點(diǎn)名稱(chēng)。
5)使用cluster集群模式,設(shè)置harbor=0。
6)主服務(wù)為main,根據(jù)luaservice項(xiàng)的配置,skynet會(huì)啟動(dòng)service/main.lua作為主服務(wù)。
config.node2與config.node1的內(nèi)容一樣,只是將node="node1"改成了node="node2"。
3.3.3 第1版主服務(wù)
先編寫(xiě)個(gè)最簡(jiǎn)單的主服務(wù),用于測(cè)試。首先要讓系統(tǒng)能啟動(dòng),后面才好編寫(xiě)功能邏輯。下面的代碼3-2僅僅能打印出“[start main]”。
代碼3-2 service/main.lua
local skynet = require "skynet" skynet.start(function() --初始化 skynet.error("[start main]") --退出自身 skynet.exit() end)
3.3.4 啟動(dòng)腳本
編譯Skynet后,即可啟動(dòng)程序,在start.sh所在的目錄執(zhí)行“./skynet/skynet./etc/config.node1”啟動(dòng)程序,圖3-7所示是成功啟動(dòng)服務(wù)端項(xiàng)目的信息,倒數(shù)第三行的“[start main]”正是主服務(wù)打印出的內(nèi)容,如果能看到此信息,說(shuō)明啟動(dòng)成功。

圖3-7 成功啟動(dòng)服務(wù)端項(xiàng)目
“./skynet/skynet./etc/config.node1”這句話(huà)很長(zhǎng),不方便輸入,在start.sh中編寫(xiě)如代碼3-3所示的代碼以后,只需執(zhí)行“sh start.sh 1”即可開(kāi)啟第一個(gè)節(jié)點(diǎn),執(zhí)行“sh start.sh 2”即可開(kāi)啟第二個(gè)節(jié)點(diǎn),方便多了。
代碼3-3 ./start.sh
./skynet/skynet ./etc/config.node$1
3.3.5 服務(wù)配置
服務(wù)端支持橫向拓展,每個(gè)節(jié)點(diǎn)可以開(kāi)啟不同數(shù)量的gateway、login,此處需要通過(guò)一份配置文件來(lái)描述服務(wù)端的拓?fù)浣Y(jié)構(gòu)。各個(gè)服務(wù)也需要根據(jù)這份配置文件來(lái)查找其他服務(wù)的位置。比如login服務(wù)器需要與agentmgr通信,那么它就需要知道agentmgr在哪個(gè)節(jié)點(diǎn),配置文件會(huì)提供這個(gè)信息。服務(wù)配置還會(huì)提供服務(wù)所需的一些參數(shù),比如每個(gè)gateway監(jiān)聽(tīng)哪個(gè)端口號(hào)。
新建文件etc/runconfig.lua,內(nèi)容如代碼3-4所示。
代碼3-4 etc/runconfig.lua
return { --集群 cluster = { node1 = "127.0.0.1:7771", node2 = "127.0.0.1:7772", }, --agentmgr agentmgr = { node = "node1" }, --scene scene = { node1 = {1001, 1002}, --node2 = {1003}, }, --節(jié)點(diǎn)1 node1 = { gateway = { [1] = {port=8001}, [2] = {port=8002}, }, login = { [1] = {}, [2] = {}, }, }, --節(jié)點(diǎn)2 node2 = { gateway = { [1] = {port=8011}, [2] = {port=8022}, }, login = { [1] = {}, [2] = {}, }, }, }
代碼3-4雖然看起來(lái)比較長(zhǎng),含義卻很簡(jiǎn)單,圖3-8對(duì)代碼中各項(xiàng)做出了解釋?zhuān)瑢?duì)于圖3-3涉及的agent和nodemgr,因?yàn)闊o(wú)須配置,所以不在圖里展現(xiàn)。以下是代碼3-4的具體說(shuō)明。
1)cluster項(xiàng)指明服務(wù)端系統(tǒng)包含兩個(gè)節(jié)點(diǎn),分別為node1和node2。各個(gè)節(jié)點(diǎn)需要通信,其中node1的地址為“127.0.0.1:7771”,node2的地址為“127.0.0.1:7772”。
2)agentmgr項(xiàng)指明全局唯一的agentmgr服務(wù)位于節(jié)點(diǎn)1處。
3)scene項(xiàng)指明在節(jié)點(diǎn)1開(kāi)啟編號(hào)為1001和1002的兩個(gè)戰(zhàn)斗場(chǎng)景服務(wù),語(yǔ)句“node2={1003}”代表在節(jié)點(diǎn)2開(kāi)啟編號(hào)為1003的場(chǎng)景服務(wù)。為了方便前期開(kāi)啟單個(gè)節(jié)點(diǎn)來(lái)調(diào)試功能,我們先把node2={1003}這行代碼注釋掉,用時(shí)再開(kāi)啟。
4)node1和node2描述了各節(jié)點(diǎn)的“本地”服務(wù)。兩個(gè)節(jié)點(diǎn)分別開(kāi)啟了兩個(gè)gateway和兩個(gè)login,節(jié)點(diǎn)1處的兩個(gè)gateway的監(jiān)聽(tīng)端口分別是8001和8002,節(jié)點(diǎn)2的是8011和8012。
這段代碼僅是范例,讀者可以根據(jù)項(xiàng)目需要自行修改。如果游戲在線(xiàn)人數(shù)很多,要配置更多節(jié)點(diǎn),開(kāi)啟更多gateway。
后面的主程序會(huì)讀取runconfig.lua,決定節(jié)點(diǎn)內(nèi)要啟動(dòng)哪些服務(wù)。gateway也會(huì)讀取它,用于設(shè)置監(jiān)聽(tīng)端口。

圖3-8 代碼3-4描述的結(jié)構(gòu)
該如何讀取這份描述文件呢?可以按照代碼3-5做個(gè)簡(jiǎn)單測(cè)試,主服務(wù)應(yīng)該能把“runconfig.agentmgr.node”的值“node1”打印出來(lái)。
代碼3-5 ./service/main.lua
local skynet = require "skynet"skynet.start(function() --初始化 --退出自身 skynet.exit() end)
- 數(shù)字媒體應(yīng)用教程
- 大學(xué)計(jì)算機(jī)應(yīng)用基礎(chǔ)實(shí)踐教程
- Vue.js快跑:構(gòu)建觸手可及的高性能Web應(yīng)用
- Django Design Patterns and Best Practices
- OpenNI Cookbook
- 信息安全技術(shù)
- Java設(shè)計(jì)模式及實(shí)踐
- Apache Mesos Essentials
- 智能手機(jī)APP UI設(shè)計(jì)與應(yīng)用任務(wù)教程
- 快速入門(mén)與進(jìn)階:Creo 4·0全實(shí)例精講
- Spring Security Essentials
- Machine Learning With Go
- Spring 5 Design Patterns
- Python 3 數(shù)據(jù)分析與機(jī)器學(xué)習(xí)實(shí)戰(zhàn)
- Oracle Data Guard 11gR2 Administration Beginner's Guide