Commit 5e5d76803222a5b31e1481ceb4102a1736bb4937

Authored by zhouhaihai
1 parent 3fe4471e

热更新 优化

src/actions/GmAction.lua
... ... @@ -15,6 +15,9 @@ function _M.clientRequest(agent, data)
15 15 return true
16 16 end
17 17  
  18 +function _M.testhotfix(role, pms)
  19 + return csvdb["itemCsv"][1]["name"]
  20 +end
18 21  
19 22 function _M.hero(role, pms)
20 23 local heroType = tonum(pms.pm1)
... ...
src/actions/HttpAction.lua
... ... @@ -5,61 +5,64 @@ local codecache = require "skynet.codecache" -- 清空缓存用
5 5  
6 6 local _M = {}
7 7  
8   --- 清空代码和csvdata 缓存 (无论什么热更新 都要先更新服务器 然后调用这个 api 再进行更新)
  8 +-- 清空缓存
9 9 function _M.clearcache(query, body)
10 10 skynet.error(string.format("clearcache time: %s", skynet.timex()))
11 11 codecache.clear()
12 12 return 'success'
13 13 end
14 14  
15   ---重新加载 csvdata -- 需要先调用 clearcache
  15 +--重新加载 需要修改的csvdb
  16 +--[=[ eg:
  17 + body = """
  18 + csvdb["itemCsv"][1]["name"] = "测试一下"
  19 + """
  20 +]=]
  21 +
16 22 function _M.reload_csvdata(query, body)
17   - skynet.error(string.format("reload_csvdata time: %s", skynet.timex()))
18   - local status = skynet.call('CSVDATA', "lua", "reload")
19   - if status == "ok" then
20   - -- 所有需要 更新的服务 都更新一下数据
21   - pcall(skynet.call, 'WATCHDOG', "lua", "reloadCsvData")
22   - pcall(skynet.call, 'NGXD', "lua", "reloadCsvdb")
  23 + if not body or body == "" then
  24 + return
23 25 end
24   - return 'success'
25   -end
26 26  
27   ---post 需要更改的 globalCsv json
28   -function _M.global_csv(query, body)
29   - if not body or body == "" then return end
30   - local change = json.decode(body) -- json 表
31   - if not next(change) then return end
32   - skynet.error(string.format("global_csv change time: %s, value: %s", skynet.timex(), body))
33   - -- 更新所有需要更新globalDefine 的地方
34   - pcall(skynet.call, 'WATCHDOG', "lua", "reloadCsvData", change)
35   - pcall(skynet.call, 'NGXD', "lua", "reloadCsvdb", change) -- 他也要改
  27 + local ok = pcall(load, body)
  28 + if not ok then return end
36 29  
37   - return 'success'
  30 + skynet.error(string.format("reload_csvdata time: %s, code: %s", skynet.timex(), body))
  31 +
  32 + local status = skynet.call('CSVDATA', "lua", "reload", body)
  33 + if status == "ok" then
  34 + return 'success'
  35 + end
38 36 end
39 37  
40 38  
41 39 -- 热更新代码 -- 针对 agent 执行发送过来的代码 -- 代码要规范~
42 40  
43 41 --[=[ eg:
44   -1. *Action 重新加载 (action 每次用才require 直接清掉重新加载) (某些)
45   - body = "package.loaded['actions.*Action']=nil"
  42 +1. *Action
  43 + body = """
  44 + _hotfixActions = _hotfixActions or {}
  45 + _hotfixActions["Gm.clientRequest"] = function(agent, data)
  46 + bin = MsgPack.pack({ cmd = "testtest" })
  47 + SendPacket(actionCodes.Gm_receiveResponse, bin)
  48 + end
  49 + """
46 50  
47 51 2. 修改 global 方法 和 变量 直接覆盖
48 52 body = """
49 53 function a()
50 54 print(123)
51 55 end
  56 +
  57 + globalCsv["asdasd"] = 12
  58 +
  59 + HEHE = 123
52 60 """
53 61  
54   -3. 修改 role 方法
  62 +3. 修改 role 方法(待定)
55 63  
56 64 body = """
57   - local role = ...
58   - if role then
59   - role.getItemCount = function(self)
60   - return "hehe"
61   - end
62   - end
  65 +
63 66 """
64 67 ]=]
65 68  
... ... @@ -67,9 +70,11 @@ function _M.hotfix(query, body)
67 70 if not body or body == "" then
68 71 return
69 72 end
70   - skynet.error(string.format("hotfix time: %s, code: %s", skynet.timex(), body))
71 73 local ok = pcall(load, body)
72 74 if not ok then return end
  75 +
  76 + skynet.error(string.format("hotfix time: %s, code: %s", skynet.timex(), body))
  77 +
73 78 pcall(skynet.call, 'WATCHDOG', "lua", "hotfix", body)
74 79 return 'success'
75 80 end
... ...
src/agent.lua
... ... @@ -16,12 +16,15 @@ skynet = require "skynet"
16 16 redisproxy = require "shared.redisproxy"
17 17 datacenter = require "skynet.datacenter"
18 18 mcast_util = require "services/mcast_util"
  19 +globalCsv = require "csvdata/GlobalDefine"
19 20  
20 21 local CMD = {}
21 22 local agentInfo = {} -- { client_fd, role, gate_serv, open_timer}
22 23  
23 24 local agent_util, cs
24 25  
  26 +_hotfixActions = _hotfixActions or {}
  27 +
25 28 --- {{{ 定时器相关
26 29 local function handle_timeout()
27 30 if not agentInfo.open_timer then return end
... ... @@ -183,16 +186,21 @@ skynet.register_protocol {
183 186 print("actionName not exist", actionName)
184 187 return
185 188 end
186   - local modName, funcName = actionName:match("(%w+)%.(%w+)")
187 189  
188   - local ok, action = pcall(require, "actions." .. modName .. "Action")
189   - if not ok then
190   - print("require module name error", action, modName)
191   - return
  190 + local method
  191 + if _hotfixActions[actionName] then
  192 + method = _hotfixActions[actionName]
  193 + else
  194 + local modName, funcName = actionName:match("(%w+)%.(%w+)")
  195 +
  196 + local ok, action = pcall(require, "actions." .. modName .. "Action")
  197 + if not ok then
  198 + print("require module name error", action, modName)
  199 + return
  200 + end
  201 + method = action[funcName]
192 202 end
193   -
194   - local method = action[funcName]
195   -
  203 +
196 204 if type(method) ~= "function" then
197 205 print("ERROR_SERVER_INVALID_ACTION", modName, funcName)
198 206 return
... ... @@ -226,7 +234,7 @@ skynet.register_protocol {
226 234 }
227 235  
228 236 -- function CMD.start(gate, fd, ip)
229   -function CMD.start(session, source, gate, fd, ip)
  237 +function CMD.start(session, source, gate, fd, ip, hotfixs)
230 238 ignoreHeartbeat = false
231 239  
232 240 agentInfo.client_fd = fd
... ... @@ -236,10 +244,9 @@ function CMD.start(session, source, gate, fd, ip)
236 244 agent_util:reset()
237 245 math.randomInit()
238 246  
239   -
240   - -- 这里加载配表 不然热更新对某些 agent 无效
241   - csvdb = sharedata.query("csvdata")
242   - globalCsv = require "csvdata/GlobalDefine"
  247 + for _, hotfix in ipairs(hotfixs) do
  248 + CMD.hotfix(hotfix)
  249 + end
243 250  
244 251 -- 这里将消息伪装成 watchdog 发出,这样就由 A->B->C->B->A 变成 A->B->C->A
245 252 skynet.redirect(gate, source, "lua", session, skynet.pack("forward", fd, 0, skynet.self()))
... ... @@ -274,20 +281,10 @@ function CMD:usubUnion()
274 281 agentInfo.userv = nil
275 282 end
276 283  
277   -function CMD.reloadCsvdb(globalData)
278   - if globalData then
279   - for k, v in pairs(globalData) do
280   - globalCsv[k] = v
281   - end
282   - else
283   - csvdb = sharedata.query("csvdata")
284   - end
285   -end
286   -
287 284 function CMD.hotfix(code)
288 285 local ok, func = pcall(load, code)
289 286 if ok then
290   - ok = pcall(func, agentInfo.role)
  287 + ok = pcall(func)
291 288 end
292 289 if not ok then
293 290 skynet.error("hotfix error by code " .. code)
... ... @@ -328,6 +325,7 @@ skynet.start(function()
328 325  
329 326 cs = queue()
330 327  
  328 + csvdb = sharedata.query("csvdata")
331 329 -- 错误码特殊处理
332 330 -- todo
333 331 -- for key, value in pairs(csvdb["sys_codesCsv"]) do
... ...
src/services/agent_ctrl.lua
... ... @@ -132,13 +132,10 @@ function _M:check_agent_status()
132 132 end
133 133 end
134 134  
135   -function _M:reload_csvdata(globalData)
136   - for uid, pack in pairs(self.u2f) do
137   - local agent = get_a(pack)
138   - pcall(skynet.send, agent, "lua", "reloadCsvdb", globalData)
139   - end
140   -end
  135 +local hotfixList = {}
  136 +
141 137 function _M:hotfix(code)
  138 + table.insert(hotfixList, code)
142 139 for uid, pack in pairs(self.u2f) do
143 140 local agent = get_a(pack)
144 141 pcall(skynet.send, agent, "lua", "hotfix", code)
... ... @@ -193,7 +190,7 @@ function _M:query_agent(fd, uid)
193 190 return
194 191 end
195 192  
196   - local ok = pcall(skynet.call, agent, "lua", "start", gate_serv, fd, self.f2i[fd])
  193 + local ok = pcall(skynet.call, agent, "lua", "start", gate_serv, fd, self.f2i[fd], hotfixList)
197 194 if not ok then
198 195 self.factory:push(agent)
199 196 query_agent_response(fd, {ret = "INNER_ERROR"})
... ...
src/services/csvdatad.lua
... ... @@ -61,19 +61,20 @@ end
61 61  
62 62  
63 63 local CMD = {}
64   -function CMD.reload()
  64 +function CMD.reload(code)
65 65 -- 重新加载 csvdata
66   - csvdb = {}
67   - for k, v in pairs(package.loaded) do
68   - if k:find("csvdata") then
69   - package.loaded[k] = nil
70   - end
  66 + csvdb = csvdb or {}
  67 +
  68 + local ok, func = pcall(load, code)
  69 + if ok then
  70 + ok = pcall(func)
  71 + end
  72 + if not ok then
  73 + skynet.error("reload_csvdata error by code " .. code)
  74 + return 'error'
71 75 end
72   - require("csvdata.init")
73   - require("csvdata.init_adv")
74 76  
75 77 sharedata.update("csvdata", csvdb)
76   - skynet.sleep(1) -- 睡一觉再返回
77 78 return 'ok'
78 79 end
79 80  
... ...
src/services/httpweb.lua
... ... @@ -9,7 +9,7 @@ require "utils.init"
9 9 local table = table
10 10 local string = string
11 11  
12   -local port, watchdog = ...
  12 +local port = ...
13 13 port = tonumber(port)
14 14  
15 15 local key = "zhaolu1234dangge"
... ...
src/services/ngxd.lua
... ... @@ -93,25 +93,10 @@ local function start()
93 93 end
94 94 end
95 95  
96   -local CMD = {}
97   -function CMD.reloadCsvdb(globalData)
98   - if globalData then
99   - for k, v in pairs(globalData) do
100   - globalCsv[k] = v
101   - end
102   - else
103   - csvdb = sharedata.query("csvdata")
104   - end
105   -end
106   -
107   -
108 96 local function __init__()
109 97 skynet.dispatch("lua", function(_,_, command, ...)
110 98 if command == "start" then
111 99 skynet.ret(skynet.pack(start(...)))
112   - else
113   - local f = CMD[command]
114   - skynet.ret(skynet.pack(f(...)))
115 100 end
116 101 end)
117 102  
... ...
src/services/watchdog.lua
... ... @@ -89,10 +89,6 @@ function CMD.forceClose(fd)
89 89 agent_ctrl:exit_agent(fd)
90 90 end
91 91  
92   -function CMD.reloadCsvData(globalData)
93   - agent_ctrl:reload_csvdata(globalData)
94   -end
95   -
96 92 function CMD.hotfix(code)
97 93 agent_ctrl:hotfix(code)
98 94 end
... ...