- 新增 lua-embed-analysis.md 技术分析文档 - 新增 lua-nginx-module 文档目录 - 更新 gitignore 允许跟踪 docs/lua-nginx-module/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7.2 KiB
7.2 KiB
lua-nginx-module 核心架构设计
本文档为 lolly 项目提供 lua-nginx-module 的核心架构参考。
一、核心数据结构
1.1 主配置结构 (ngx_http_lua_main_conf_t)
文件: src/ngx_http_lua_common.h:233
struct ngx_http_lua_main_conf_s {
lua_State *lua; // Lua VM 实例
ngx_hash_t shm_zones; // 共享内存区域
ngx_array_t *shdict_zones; // shdict 区域
// Phase handlers
ngx_http_handler_pt init_handler;
ngx_http_handler_pt init_worker_handler;
ngx_http_handler_pt exit_worker_handler;
// 线程缓存
ngx_queue_t free_lua_threads;
ngx_queue_t cached_lua_threads;
// 功能开关
unsigned requires_rewrite:1;
unsigned requires_access:1;
unsigned requires_log:1;
// ...
};
1.2 请求上下文 (ngx_http_lua_ctx_t)
文件: src/ngx_http_lua_common.h:628
struct ngx_http_lua_ctx_s {
ngx_http_request_t *request; // 请求对象
// 协程管理
ngx_http_lua_co_ctx_t *cur_co_ctx; // 当前协程
ngx_http_lua_co_ctx_t entry_co_ctx; // 入口协程
ngx_queue_t user_co_ctx; // 用户协程列表
// 输出缓冲
ngx_chain_t *out;
ngx_chain_t *free_bufs;
ngx_chain_t *busy_bufs;
// 请求体
ngx_chain_t *body;
ngx_chain_t *filter_in_bufs;
// 状态
unsigned context; // 当前 phase
unsigned exited:1;
unsigned eof:1;
// ...
};
1.3 协程上下文 (ngx_http_lua_co_ctx_t)
文件: src/ngx_http_lua_common.h:550
struct ngx_http_lua_co_ctx_s {
lua_State *co; // Lua 协程
ngx_http_lua_co_status_e co_status; // 状态
// 父子关系
ngx_http_lua_co_ctx_t *parent_co_ctx;
ngx_queue_t zombie_child_threads;
// 子请求数据
ngx_int_t *sr_statuses;
ngx_http_headers_out_t **sr_headers;
ngx_str_t *sr_bodies;
// 挂起状态
unsigned sleep:1;
unsigned sem_wait:1;
// ...
};
二、Nginx 集成机制
2.1 Directive 注册
文件: src/ngx_http_lua_module.c:114-804
static ngx_command_t ngx_http_lua_cmds[] = {
{ ngx_string("content_by_lua_block"),
NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK,
ngx_http_lua_content_by_lua_block,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_lua_loc_conf_t, content_handler),
NULL },
// ... 更多指令
};
2.2 Handler 注册
文件: src/ngx_http_lua_module.c:839-945
static ngx_int_t ngx_http_lua_init(ngx_conf_t *cf)
{
// 动态注册 phase handlers
if (lmcf->requires_rewrite) {
h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
*h = ngx_http_lua_rewrite_handler;
}
// Filter chain 注册
ngx_http_lua_header_filter_init();
ngx_http_lua_body_filter_init();
}
2.3 Filter Chain
// Header filter
ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_lua_header_filter;
// Body filter
ngx_http_next_body_filter = ngx_http_top_body_filter;
ngx_http_top_body_filter = ngx_http_lua_body_filter;
三、请求处理流程
nginx 请求
↓
ngx_http_lua_content_handler
↓
ngx_http_lua_content_run
↓
ngx_http_lua_run_thread ←───┐
↓ │
lua_pcall / lua_resume │
↓ │
用户 Lua 代码 │
│ │
├── lua_yield ───────────┘ (NGX_AGAIN)
│ ↓
│ 事件注册
│ ↓
│ resume_handler
│ ↓
│ 恢复执行
│
└── return
↓
NGX_OK / NGX_ERROR
四、协程驱动架构
4.1 Yield/Resume 机制
// Yield
lua_yield(L, nresults); // 挂起 Lua 协程
ctx->resume_handler = ...; // 设置恢复函数
return NGX_AGAIN; // 让出 nginx 控制权
// Resume
resume_handler(r); // 事件触发时调用
lua_resume(L, nargs); // 恢复 Lua 协程
4.2 非阻塞 I/O 模式
ngx.sleep(1)
│
├── 添加 nginx 定时器
├── lua_yield
└── return NGX_AGAIN
↓
nginx 处理其他请求
↓
定时器到期
↓
ngx_http_lua_sleep_handler
↓
lua_resume
↓
用户代码继续
五、内存管理策略
5.1 双重内存管理
| 场景 | 使用 |
|---|---|
| 请求临时数据 | ngx_palloc(r->pool) / ngx_pfree() |
| 长期对象 | lua_newuserdata() (Lua GC) |
5.2 请求对象获取
#ifdef OPENRESTY_LUAJIT
// 使用 exdata (更快)
r = lua_getexdata(L);
#else
// 全局变量
lua_getglobal(L, "__ngx_req");
r = lua_touserdata(L, -1);
#endif
六、设计模式总结
| 模式 | 说明 |
|---|---|
| Phase-based | Nginx 11 个 phase,每个可注册 Lua handler |
| 协程驱动 | 非阻塞 I/O 通过 yield/resume 与 nginx 事件循环协作 |
| VM 共享 | per-worker 单 VM,协程实现请求隔离 |
| Closure Factory | 非 LuaJIT 环境隔离 upvalue |
| Filter Chain | 插入式 header/body 过滤 |
七、关键设计决策
7.1 为什么用协程?
- 同步代码风格: 开发者写同步代码,框架处理异步
- 非阻塞: yield 时 nginx 可以处理其他请求
- 简单错误处理: 使用标准 Lua 错误机制
7.2 为什么单 VM?
- 内存效率: 代码只加载一次
- 共享状态: 全局变量和缓存自然共享
- 性能: 无 VM 切换开销
7.3 为什么用 FFI?
- 性能: 绕过 Lua C API 开销
- 简洁: 直接调用 C 函数
- 灵活: 可动态加载
八、lolly 实现参考
8.1 核心模块实现顺序
- VM 管理: Lua 状态机创建、初始化、销毁
- Context 管理: 请求上下文、协程上下文
- Phase Handlers: 各阶段的 handler 注册和执行
- Yield/Resume: 协程挂起和恢复机制
- API 注入: ngx.* 命名空间构建
8.2 需要实现的 C API
// VM 管理
lua_State *create_vm();
void destroy_vm(lua_State *L);
// 协程管理
int run_thread(lua_State *L, lua_State *co);
int yield_thread(lua_State *co, int nresults);
int resume_thread(lua_State *co, int nargs);
// 请求对象
ngx_http_request_t *get_request(lua_State *L);
void set_request(lua_State *L, ngx_http_request_t *r);
// Phase 执行
int run_phase_handler(ngx_http_request_t *r, int phase);
8.3 数据结构映射
| lua-nginx-module | lolly 参考 |
|---|---|
ngx_http_lua_main_conf_t |
全局配置,VM 管理 |
ngx_http_lua_loc_conf_t |
Location 配置,handler 存储 |
ngx_http_lua_ctx_t |
请求级上下文 |
ngx_http_lua_co_ctx_t |
协程状态管理 |