lolly/docs/lua-nginx-module/11-architecture.md
xfy 941c44b798 docs: 添加 Lua 嵌入分析文档
- 新增 lua-embed-analysis.md 技术分析文档
- 新增 lua-nginx-module 文档目录
- 更新 gitignore 允许跟踪 docs/lua-nginx-module/

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 11:20:57 +08:00

7.2 KiB
Raw Blame History

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 核心模块实现顺序

  1. VM 管理: Lua 状态机创建、初始化、销毁
  2. Context 管理: 请求上下文、协程上下文
  3. Phase Handlers: 各阶段的 handler 注册和执行
  4. Yield/Resume: 协程挂起和恢复机制
  5. 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 协程状态管理