官术网_书友最值得收藏!

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  =  "./service/?.lua;" .."./service/?/init.lua;".. "./skynet/service/?.
    lua;"
lua_ path  =  "./etc/?.lua;" .. "./lualib/?.lua;" ..  "./skynet/lualib/?.
    lua;" .. "./skynet/lualib/?/init.lua"
lua_cpath = "./luaclib/?.so;" .. "./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"
local runconfig = require "runconfig"

skynet.start(function()
    --初始化
    skynet.error(runconfig.agentmgr.node)
    --退出自身
    skynet.exit()
end)

主站蜘蛛池模板: 四会市| 湟源县| 鹤山市| 邳州市| 平凉市| 嘉祥县| 广昌县| 霞浦县| 留坝县| 香港 | 双流县| 阿拉善左旗| 宜良县| 曲周县| 铁力市| 清苑县| 阿合奇县| 金秀| 临沧市| 沐川县| 开封市| 洞头县| 昭苏县| 兴业县| 兴和县| 泗阳县| 赤城县| 邛崃市| 黄浦区| 酉阳| 宁海县| 德化县| 靖远县| 苗栗市| 江山市| 安陆市| 博野县| 辽阳县| 常宁市| 皋兰县| 明水县|