【基于skyent的热更思考】

基于skyent的热更思考

skynet-inject热更原理

inject是一个用于动态加载 Lua 代码文件并执行其中定义的函数的功能。可以在运行时动态加载 Lua 代码文件,然后调用其中定义的函数,通过修改模块及其函数的upvalue,实现代码的动态注入和执行。热更实现的大概思路:通过向指定服务注入cmd实现热更

参考wiki https://blog.codingnow.com/2016/11/lua_update.html

关键源码分析

lua 复制代码
-- debug_console.lua

local function adjust_address(address)
    local prefix = address:sub(1,1)
    if prefix == '.' then
        return assert(skynet.localname(address), "Not a valid name")
    elseif prefix ~= ':' then
        address = assert(tonumber("0x" .. address), "Need an address") | (skynet.harbor(skynet.self()) << 24)
    end
    return address
end


function COMMAND.inject(address, filename, ...)
    address = adjust_address(address)
    local f = io.open(filename, "rb")
    if not 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 == false then
        error(output)
    end
    return output
end

adjust_address: 用于调整传入的地址参数,对传入的地址参数进行转换,以保证将热更脚本注入到正确的服务地址
io.open(filename, "rb"): 以二进制只读的方式读取文件内容
source: 存放读取到的热更脚本内容
skynet.call(address, "debug", "RUN", ...): 通过skynet的debug消息类型,将读取的热更脚本内容注入到目标服务地址(debug.RUN内部实现)

lua 复制代码
-- skynet.debug.lua

function dbgcmd.RUN(source, filename, ...)
    local inject = require "skynet.inject"
    local args = table.pack(...)
    local ok, output = inject(skynet, source, filename, args, export.dispatch, skynet.register_protocol)
    collectgarbage "collect"
    skynet.ret(skynet.pack(ok, table.concat(output, "\n")))
end
lua 复制代码
-- skynet.inject.lua

return function(skynet, source, filename, args, ...)
    if filename then
        filename = "@" .. filename
    else
        filename = "=(load)"
    end
    local output = {}

    local function print(...)
        local value = { ... }
        for k,v in ipairs(value) do
            value[k] = tostring(v)
        end
        table.insert(output, table.concat(value, "\t"))
    end
    local u = {}
    local unique = {}
    local funcs = { ... }
    for k, func in ipairs(funcs) do
        getupvaluetable(u, func, unique)
    end
    local p = {}
    local proto = u.proto
    if proto then
        for k,v in pairs(proto) do
            local name, dispatch = v.name, v.dispatch
            if name and dispatch and not p[name] then
                local pp = {}
                p[name] = pp
                getupvaluetable(pp, dispatch, unique)
            end
        end
    end
    local env = setmetatable( { print = print , _U = u, _P = p}, { __index = _ENV })
    local func, err = load(source, filename, "bt", env)
    if not func then
        return false, { err }
    end
    local ok, err = skynet.pcall(func, table.unpack(args, 1, args.n))
    if not ok then
        table.insert(output, err)
        return false, output
    end

    return true, output
end

这两段核心代码实现了一个动态加载和执行 Lua 代码的功能,通过构建环境表、加载代码并执行,最终返回执行结果。这个函数是实现动态注入功能的关键部分,能够实现在 Skynet 框架中动态加载并执行 Lua代码,完成注入热更脚本

热更方式

  1. 可以直接在debug控制台通过调用inject将指定代码注入到指定地址实现,但对于同类型的服务需要手动依次执行,效率较低
  2. 可通过实现sh脚本获取到指定服务地址(例如hotfix服),然后在框架中的hotfix服内实现对框架类型服务的热更lua脚本
  3. 实现sh脚本,用于启动debug控制台,执行热更逻辑
  4. 添加hotcfg,用于配置需要热更的服务与要执行lua脚本路径,并定义lua脚本
  5. 根据框架架构(单点 or 集群),在hotfix服务中实现获取指定服务组的addr
  6. 通过配置的hotcfg实现将lua热更脚本依次注入到目标服务中

拓扑图

方案1:

方案2:

注意事项

  1. 要注意新代码与原有代码的兼容性,避免因为接口变更或依赖关系导致运行时错误
  2. 要注意避免对全局环境造成非预期的影响,尽量将修改限制在局部代码范围内
  3. 需要加入足够的异常处理机制,以在热更新过程中出现异常情况时能够及时捕获并处理,以保证系统的稳定性
  4. 在进行热更新前最好制定好回滚策略,以便在更新失败时能够及时恢复到原有的稳定状态
  5. 尽量避免热更新过程对系统性能造成过大影响,可以在适当的时机进行优化,减少更新对系统性能的影响
  6. 在进行热更新时建议增加详细的日志记录和监控机制,以便随时监测更新过程中的各种信息并进行分析
相关推荐
吾爱星辰2 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
ChinaDragonDreamer2 小时前
Kotlin:2.0.20 的新特性
android·开发语言·kotlin
IT良2 小时前
c#增删改查 (数据操作的基础)
开发语言·c#
Kalika0-03 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
_.Switch3 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
代码雕刻家3 小时前
课设实验-数据结构-单链表-文教文化用品品牌
c语言·开发语言·数据结构
一个闪现必杀技3 小时前
Python入门--函数
开发语言·python·青少年编程·pycharm
Fan_web3 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
龙图:会赢的3 小时前
[C语言]--编译和链接
c语言·开发语言
网络研究院4 小时前
Android 安卓内存安全漏洞数量大幅下降的原因
android·安全·编程·安卓·内存·漏洞·技术