Hotfix - changnet/MServer GitHub Wiki

热更原理

此服务器提供了Lua脚本面向对象编程,这一特性依赖于oo.lua和Lua的元表。在创建类时,所有的方法会存放到元表当中,并交给oo.lua管理。创建对象,数据存储在table本身,而元表则指向一个公共的元表。热更时,只要更新该元表中的方法即可,而无需改变对象本身的数据。

注:采用元表的方法,会有一定效率的损耗。在使用三重继承时,单纯的函数调用比直接调用函数损 失2/3的性能。

重新加载文件的原理,则是利用require对应文件时,package.loaded为nil,即可重新加载文件。但是这里应该要注意热更时并不是package.loaded中所有的字段都可以清空的。框架启动时,会有系统库(math、string、os...)和C++库注册到package.loaded中,这些是不能重新加载的。不过好在这些库的优先级较高,在lua脚本入口处重写require函数即可知道哪些是后续加载的库。

热更入口

  • 通过gm热更通过执行shell目录下的sh ./gm.sh @ghf
  • web控制台入口。具体参考http/www/hot_fix.lua这一文件中的例子

不可热更的文件

  • oo.lua本身
  • 入口文件main.lua

PS:这两个文件改一下也是可以热更的,但貌似没必要。

schema文件的热更(pb、bfbs)

schema文件是在C++那边加载的,各个库的处理方式也不一样。在增量热更时,需要指定schema字段表示是否需要重新加载schema文件,如果是全局热更默认是重新加载的。具体逻辑参考hot_fix.lua

热更影响协议转发

在热更时,会自动记录是否注册过协议回调,如果注册了,则会自动广播给其他服务器。

不可热更的功能

设计这个服务器的时候,内存中的数据是存放在Lua脚本的,所以无法热更数据部分。那么做功能的时候,就不要把逻辑放在数据中,比如不要把一个函数回调存放在数据中。

self.callback = function()
end

遇到这样的功能,目前提供一些解决方法:

  1. 回调固定的函数。比如协议回调到C++都是固定的global函数
  2. 热更时覆盖回调函数
  3. 回调函数写成一个闭包,这个参考协议回调方式
  4. 回调函数用字符串表示

如果一小心写了不可热更的函数,又急需热更时,可以用bug修复的方式写个补丁去覆盖回调函数。通过GM运行此补丁。

需要注意的时,目前的设计,新增玩家子模块无法热更。因为没办法直接把模块加到玩家身上。

其他问题

全局热更带来潜在的问题是,如果整个项目过大,脚本、配置文件过多,重新加载会大费较长时间,甚至导致全服玩家掉线。不过在实际项目,一个运营很久的ARPG项目,脚本文件(包括配置)总量过万,大小超过16M,全部重新加载(包括对配置做预处理)在5s以内,影响不大。

⚠️ **GitHub.com Fallback** ⚠️