master / slave 配置文件均沿用前一篇文章:skynet master/slave 模式。
一、測試腳本
main.lua:根據配置文件判斷當前節點是否爲 master,並對指定地址進行監聽。
local skynet = require "skynet"
local socket = require "skynet.socket"
local cluster = require "skynet.cluster"
skynet.start(function()
local nodeName = skynet.getenv("nodename") --根據配置項:nodename,判斷當前節點是否爲 master
local isMaster = nodeName == "cluster_center"
if isMaster then
--[[
cluster.reload:主要用來將節點名與地址保存到表 node_address 中,方便後續發起遠程請求,如 cluster.send 或者 cluster.call。
__nowaiting解釋:當一個名字沒有配置在配置表中時,如果你向這個未命名節點發送一個請求,skynet 的默認行爲是掛起,
一直等到這個名字對應項的配置被更新。你可以通過配置節點名字對應的地址爲 false 來明確指出這個節點已經下線。
另外,可以通過在配置表中插入 __nowaiting = true 來關閉這種掛起行爲
--]]
cluster.reload({
__nowaiting = true,
tunnel1 = "192.168.255.128:50001", -- master 監聽通道1(普通通道)
tunnel2 = "192.168.255.128:50002", -- master 監聽通道2(優先通道),兩個通道的原因是因爲有些消息具有較高的優先級
tunnel3 = "192.168.255.128:60001", -- master 可訪問的其他服務節點
})
-- master 打開並監聽這兩個地址
cluster.open("tunnel1")
cluster.open("tunnel2")
else
cluster.reload({
__nowaiting = false,
tunnel1 = "192.168.255.128:50001", -- master 普通通道
tunnel2 = "192.168.255.128:50002", -- master 優先通道
tunnel3 = "192.168.255.128:60001", -- 當前 slave 節點監聽地址
})
cluster.open("tunnel3")
end
local theService = skynet.newservice("glpTestCluster")
skynet.exit()
end)
glpTestCluster.lua:slave 節點首先走 tunnel1 通道,調用 master 節點註冊的 fish 服務的 testA 方法;master 節點收到消息後,testA 方法會判斷當前是否爲 master,是的話就 fork 一個新協程走 tunnel3 通道,調用 slave 節點註冊的 fish1 服務的 testA 方法。
local skynet = require "skynet"
require "skynet.manager"
local cluster = require "skynet.cluster"
local isMaster = false
function clusterPrint(...)
print("glpTestCluster [" .. skynet.address(skynet.self()) .. "] " .. os.date("%Y-%m-%d %X") .. ']:', ...)
end
local Funcs = {}
function Funcs.testSelf(agent)
clusterPrint("testSelf agent==self", agent == skynet.self(), skynet.address(agent))
end
function Funcs.test(val)
clusterPrint("test val=", val)
return val
end
function Funcs.testA(val, usr)
clusterPrint("testA usr=", usr, "val=", val)
if isMaster then
skynet.fork(function()
skynet.sleep(100)
local status, ret = pcall(function()
return cluster.call("tunnel3", "@fish1", "testA", 3, "American")
end)
clusterPrint("status=", status, "ret=", ret)
end)
end
return val
end
-- 測試cluster組網
skynet.start(function()
clusterPrint("skynet.start glpTestCluster")
isMaster = skynet.getenv("nodename") == "cluster_center"
skynet.dispatch("lua", function(session, source, funcName, ...)
clusterPrint("test dispatch", session, source, funcName, ...)
local f = Funcs[funcName]
if f then
skynet.retpack(f(...))
else
clusterPrint("Error no function =", funcName)
end
end)
local f
if isMaster then
--[[
註冊本服務的名字
注意:若服務只用於當前節點,則名字最好以“.”開頭,表示本地節點服務,不能被其他節點調用(如果調用會報錯)
若需被其他節點調用,則前面不帶點
--]]
cluster.register("fish")
else
cluster.register("fish1")
f = function()
clusterPrint("call the tunnel1")
local status, ret = pcall(function()
--[[
cluster.call():
參數一:想走的通道,切忌調用自己監聽的通道,這樣會報錯。
參數二: @ + 服務名稱
參數三:方法名
參數四:方法的參數
--]]
return cluster.call("tunnel1", "@fish", "testA", 1, "Chinese")
end)
clusterPrint("status=", status, "ret=", ret)
skynet.timeout(300, f)
end
end
if f then
f()
end
end)
二、測試結果
master:
slave: