--main.lua local skynet = require"skynet" skynet.start(function() skynet.newservice("debug_console", "127.0.0.1", "9666") local addr = skynet.newservice("serviceA")
localfunctiontick() skynet.send(addr, "lua", "foo") skynet.send(addr, "lua", "bar") skynet.timeout(500, tick) end
skynet.timeout(500, tick) end)
在服务serverA中,我们根据参数,调用不同的处理函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
--serviceA.lua local skynet = require"skynet" local handles = {}
handles.foo = function() print("foo") end
skynet.start(function() skynet.dispatch("lua", function(session, source, cmd, ...) local handle = handles[cmd] if handle then handle() else print("cmd not found", cmd) end end) end)
现在我们启动skynet,可以看到每隔5秒输出:
1 2
foo cmd not found bar
现在我们新建一个文件hotfix.lua:
1 2 3 4 5 6 7 8 9 10
--hotfix.lua local handles = _P.lua.handles localprint = _G.print handles.foo = function() print("foo after hotfix") end
handles.bar = function() print("bar after hotfix") end
--serviceA.lua local skynet = require"skynet" local handles = {}
local N = 1 local T = { count = 0, }
handles.foo = function() N = N + 2 T.count = T.count + 1 print("foo", N, T.count) end
handles.bar = function() N = N - 1 print("bar", N) end
skynet.start(function() skynet.dispatch("lua", function(session, source, cmd, ...) local handle = handles[cmd] if handle then handle() else print("cmd not found", cmd) end end) end)
foo函数带有两个upValue: N和T,bar函数带有一个upValue: N 如果hotfix.lua文件没有做特殊处理,直接覆盖函数的话,那么就会丢失这些upValue。那么,要怎么处理这些upValue呢?这里需要用到lua的debug库,主要是两个函数:
debug.getupvalue(f, i): 获取函数f中的第i个upValue的变量名和值。
debug.upvaluejoin(f1, i, f2, j):让函数f1的第i个upValue引用f2中的第j个upValue。
local handles = _P.lua.handles localprint = _G.print
localfunctionget_up(f) local u = {} ifnot f then return u end local i = 1 whiletruedo local name = debug.getupvalue(f, i) if name == nilthen return u end u[name] = i i = i + 1 end return u end
localfunctionuv_join(f, old_f, old_uv) local i = 1 whiletruedo local name = debug.getupvalue(f, i) ifnot name then break end
if old_uv[name] then debug.upvaluejoin(f, i, old_f, old_uv[name]) end i = i + 1 end end
local foo = handles.foo local up = get_up(foo)
local N, T --定义两个upValue,否则函数里会变成全局变量 handles.foo = function() N = N + 200 T.count = T.count + 100 print("foo", N, T.count) end uv_join(handles.foo, foo, up)
--debug_console.lua functionCOMMAND.inject(address, filename, ...) address = adjust_address(address) local f = io.open(filename, "rb") ifnot f then return"Can't open " .. filename end local source = f:read"*a" f:close() local ok, output = skynet.call(address, "debug", "RUN", source, filename, ...) if ok == falsethen error(output) end returnoutput end