每个在线客户端都要定时发心跳保活,一万在线就是每秒上百个心跳包,其中九成来自挂机与后台窗口。心跳分级按客户端状态切间隔:前台六十秒一次、后台三百秒一次、战斗中十五秒一次,心跳量直降七成,掉线感知却不变慢。
客户端按前后台状态与战斗状态上报分档,服务端校验状态合法性后记录当前档位;档位切换由状态变化触发,不做定时轮询。示例代码如下:
-- 心跳分级:档位判定
local INTERVALS = {combat = 15, foreground = 60, background = 300}
local player = class(actor)
local function applyHeartbeatLevel(player, state)
local sec = INTERVALS[state]
if sec == nil then
sec = INTERVALS.foreground
end
setplayvar(player, "HUMAN", "HbLevel", state, true)
setplayvar(player, "HUMAN", "HbInterval", sec, true)
sendmsg(player, 1, 0, "心跳间隔已调整为 " .. sec .. " 秒。")
return sec
end
掉线判定随档位动态放大:后台档的容忍窗口是前台的五倍;战斗中的角色即使后台化也按战斗档计时,防止打一半被误踢。示例代码如下:
-- 掉线判定:超时容忍
local player = class(actor)
local function checkAlive(player, lastBeatTs, nowTs, inCombat)
local level = getplayvar(player, "HUMAN", "HbLevel")
local limit = INTERVALS[level] or 60
if inCombat then
limit = INTERVALS.combat * 3
end
if nowTs - lastBeatTs > limit * 2 then
sendmsg(player, 1, 0, "连接已断开,正在保存数据。")
return false
end
return true
end
三种状态切换实测:切后台心跳间隔平滑放大到三百秒、回前台立即恢复六十秒、战斗中切后台仍按战斗档 15 秒保护。掉线判定在每档下分别验证,战斗中后台化 30 分钟不误踢。上线后对比心跳总量下降七成,掉线误判率零增长;监控各档位在线占比,后台档占比超过六成说明挂机严重,那是另一个治理课题。
档位切换依赖客户端上报,脚本伪造战斗状态永远享受短间隔,服务端用最近伤害时间戳交叉校验战斗状态。心跳曾承担业务功能(顺带同步邮件数),心跳一省略邮件红点就不更新,业务功能剥离到独立推送。后台档三百秒间隔在部分路由器上被 NAT 超时掐断,后台档下探到二百四十秒并配合下发保活提示,网络层的坑要在真实环境里踩过才知道。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
实战应用:用在哪里 蜈蚣洞深处的黑暗区域是老传奇最经典的压迫感来源:没有火把,屏幕只剩身边一圈微光,黑暗里随时窜出钳虫。视野…
实战应用:用在哪里 行会管理层每周要给成员发福利邮件,一封封发到崩溃。邮件撰写面板支持附件拖拽与群发名单:从背包把物品拖进附…
实战应用:用在哪里 顶级装备直接掉落太破坏生态,长期不掉又让人绝望。碎片兑换把屠龙这样的神器拆成六十块碎片:野外精英怪概率掉…
实战应用:用在哪里 沙巴克守城最怕城防形同虚设:城墙上没箭、城门后没药、守军没人指挥补给。军备库玩法把城防物资做成一套捐献与…
实战应用:用在哪里 金币靠打、元宝靠充,两种货币一旦混在一个变量里记账,对不上账的时候谁都说不清。货币钱包把金币、元宝、绑元…
实战应用:用在哪里 每个在线客户端都要定时发心跳保活,一万在线就是每秒上百个心跳包,其中九成来自挂机与后台窗口。心跳分级按客…