feat(lua): add LState pool configuration and fix coroutine error handling

- Add LStatePoolInitialSize and LStatePoolMaxSize config fields
- Set pool defaults to 100 initial / 1000 max (matching MaxConcurrentCoroutines)
- Fix middleware to return 500 on coroutine init failure instead of continuing
- Pass pool config from server init to Lua engine with zero-value fallbacks

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
xfy 2026-05-09 11:13:23 +08:00
parent 6c7cf73c87
commit f3f92c7922
5 changed files with 22 additions and 5 deletions

View File

@ -69,6 +69,8 @@ func DefaultConfig() *Config {
CodeCacheSize: 1000,
EnableFileWatch: true,
MaxExecutionTime: 30 * time.Second,
LStatePoolInitialSize: 100,
LStatePoolMaxSize: 1000,
},
},
Static: []StaticConfig{{
@ -335,6 +337,8 @@ func GenerateConfigYAML(cfg *Config) ([]byte, error) {
fmt.Fprintf(&buf, " # coroutine_stack_size: %d # 协程栈大小0=使用默认值)\n", cfg.Servers[0].Lua.GlobalSettings.CoroutineStackSize)
fmt.Fprintf(&buf, " # coroutine_pool_warmup: %d # 协程池预热数量0=不预热)\n", cfg.Servers[0].Lua.GlobalSettings.CoroutinePoolWarmup)
fmt.Fprintf(&buf, " # minimize_stack_memory: %v # 最小化栈内存使用\n", cfg.Servers[0].Lua.GlobalSettings.MinimizeStackMemory)
fmt.Fprintf(&buf, " # lstate_pool_initial_size: %d # LState池初始大小\n", cfg.Servers[0].Lua.GlobalSettings.LStatePoolInitialSize)
fmt.Fprintf(&buf, " # lstate_pool_max_size: %d # LState池最大大小\n", cfg.Servers[0].Lua.GlobalSettings.LStatePoolMaxSize)
buf.WriteString("\n")
// static 配置

View File

@ -208,4 +208,10 @@ type LuaGlobalSettings struct {
// MinimizeStackMemory 启用栈内存自动收缩以减少内存占用
MinimizeStackMemory bool `yaml:"minimize_stack_memory"`
// LStatePoolInitialSize LState 池初始大小(预热数量)
LStatePoolInitialSize int `yaml:"lstate_pool_initial_size"`
// LStatePoolMaxSize LState 池最大大小(与 MaxConcurrentCoroutines 匹配)
LStatePoolMaxSize int `yaml:"lstate_pool_max_size"`
}

View File

@ -87,8 +87,8 @@ func DefaultConfig() *Config {
EnableLoadLib: false,
CoroutineStackSize: 64, // 优化:较小的栈减少内存分配
MinimizeStackMemory: true,
CoroutinePoolWarmup: 4, // 预热4个协程结构
LStatePoolInitialSize: 10, // LState 池预热 10 个
LStatePoolMaxSize: 100, // LState 池最大 100
CoroutinePoolWarmup: 4, // 预热4个协程结构
LStatePoolInitialSize: 100, // LState 池预热 100 个
LStatePoolMaxSize: 1000, // LState 池最大 1000(与 MaxConcurrentCoroutines 匹配)
}
}

View File

@ -169,10 +169,9 @@ func (m *LuaMiddleware) Process(next fasthttp.RequestHandler) fasthttp.RequestHa
// 初始化协程
if err := luaCtx.InitCoroutine(); err != nil {
// 协程创建失败,记录错误并继续
// 协程创建失败,返回 500 错误,不继续执行后续处理器
ctx.Error(fmt.Sprintf("lua coroutine init failed: %v", err), fasthttp.StatusInternalServerError)
luaCtx.Release()
next(ctx)
return
}

View File

@ -111,6 +111,8 @@ func initLuaEngine(luaCfg *config.LuaMiddlewareConfig) (*lua.LuaEngine, error) {
EnableOSLib: false, // 安全默认值
EnableIOLib: false,
EnableLoadLib: false,
LStatePoolInitialSize: luaCfg.GlobalSettings.LStatePoolInitialSize,
LStatePoolMaxSize: luaCfg.GlobalSettings.LStatePoolMaxSize,
}
// 设置协程栈优化选项
@ -138,6 +140,12 @@ func initLuaEngine(luaCfg *config.LuaMiddlewareConfig) (*lua.LuaEngine, error) {
}
if engineCfg.MaxExecutionTime == 0 {
engineCfg.MaxExecutionTime = 30 * time.Second
}
if engineCfg.LStatePoolInitialSize == 0 {
engineCfg.LStatePoolInitialSize = 100
}
if engineCfg.LStatePoolMaxSize == 0 {
engineCfg.LStatePoolMaxSize = 1000
}
engine, err := lua.NewEngine(engineCfg)