Nginx集成Lua实现根据POST请求报文内容

Linux命令

Nginx集成Lua实现根据POST请求报文内容

2025-03-20 00:03


? Nginx+Lua动态负载策略实战指南(2024新版) 一、环境准备与模块加载 核心组件:

                                            




? Nginx+Lua动态负载策略实战指南(2024新版)


一、环境准备与模块加载

核心组件

  • OpenResty 1.25.3.1(2024最新稳定版)
  • lua-resty-core 0.1.27
  • lua-cjson 2.1.0.11
# 编译时添加LuaJIT支持
./configure --prefix=/usr/local/openresty \
           --with-luajit \
           --with-http_ssl_module \
           --with-http_realip_module

二、请求体解析配置

# 在http块中全局配置
http {
    lua_package_path "/usr/local/openresty/lualib/?.lua;;";
    lua_shared_dict request_cache 10m;  # 共享内存缓存
  
    # 启用请求体读取
    client_body_buffer_size 128k;
    client_max_body_size 10m;
}

三、动态负载策略实现

1. 主服务配置

server {
    listen 80;
  
    # 仅处理POST请求
    location /api {
        access_by_lua_block {
            -- ?️ 关键步骤:读取并解析请求体
            ngx.req.read_body()
            local body_data = ngx.req.get_body_data()
          
            if not body_data then
                ngx.log(ngx.ERR, "Empty request body")
                return ngx.exit(400)
            end
          
            -- 解析JSON数据
            local cjson = require "cjson.safe"
            local req_obj = cjson.decode(body_data)
          
            if not req_obj then
                ngx.log(ngx.ERR, "JSON decode failed")
                return ngx.exit(400)
            end
          
            -- ? 根据业务字段生成哈希键
            local routing_key = req_obj.user_id or req_obj.device_id
            if not routing_key then
                ngx.log(ngx.WARN, "Missing routing key")
                return ngx.exit(403)
            end
          
            -- 存储到共享变量
            ngx.ctx.backend_key = ngx.crc32_long(routing_key) % 4
        }
      
        proxy_pass http://dynamic_backend;
    }
}

2. 动态upstream配置

upstream dynamic_backend {
    balancer_by_lua_block {
        -- ? 负载决策核心逻辑
        local balancer = require "ngx.balancer"
        local backend_key = ngx.ctx.backend_key
      
        -- 后端服务器列表
        local backends = {
            "10.0.1.10:8080",  -- 0号节点
            "10.0.1.11:8080",  -- 1号节点
            "10.0.1.12:8080",  -- 2号节点
            "10.0.1.13:8080"   -- 3号节点
        }
      
        -- 加权轮询扩展(示例)
        local weights = {30, 20, 20, 30}  -- 总权重100
        local total = 0
        local rand = ngx.now() % 100
      
        for i=1, #weights do
            total = total + weights[i]
            if rand < total then
                backend_key = i-1
                break
            end
        end
      
        -- 设置目标后端
        local ok, err = balancer.set_current_peer(
            backends[backend_key + 1])
        if not ok then
            ngx.log(ngx.ERR, "Balancer error: ", err)
            return ngx.exit(500)
        end
    }
}

四、动态路由策略扩展

1. 基于业务类型分流

-- 在access阶段添加判断
if req_obj.biz_type == "VIP" then
    ngx.ctx.backend_group = "vip_cluster"
elseif req_obj.amount > 10000 then
    ngx.ctx.backend_group = "finance_cluster"
else
    ngx.ctx.backend_group = "default_cluster"
end

2. 多级哈希策略

local hash1 = ngx.crc32_long(routing_key)
local hash2 = ngx.crc32_short(routing_key)
local combined_hash = bit.bxor(hash1, hash2)
ngx.ctx.backend_key = combined_hash % 8

五、性能优化要点

# 1. 缓存解析结果
set $cache_key "";
access_by_lua_block {
    local key = ngx.md5(ngx.var.request_body)
    local cache = ngx.shared.request_cache
    local cached = cache:get(key)
  
    if cached then
        ngx.var.cache_key = cached
    else
        -- 解析逻辑...
        cache:set(key, routing_key, 60)  -- 缓存60秒
    end
}

# 2. 限制请求体处理
client_body_buffer_size 128k;  # 超过部分写入磁盘
lua_need_request_body on;      # 按需读取

# 3. 开启协程池
lua_socket_pool_size 30;
lua_socket_keepalive_timeout 60s;

六、调试与监控

1. 日志记录配置

log_by_lua_block {
    local latency = tonumber(ngx.var.upstream_response_time)
    ngx.log(ngx.INFO, 
        "Backend:", ngx.var.upstream_addr,
        " | Key:", ngx.ctx.backend_key,
        " | Latency:", latency)
}

2. 实时监控命令

# 查看负载分布
tail -f /var/log/nginx/access.log | awk '{print $NF}'

# 内存使用监控
watch -n 1 "echo 'cache stats' && /usr/local/openresty/luajit/bin/resty --shdict='request_cache' /tmp/dump.lua"

七、安全防护措施

# 1. 请求体大小限制
client_max_body_size 2m;  # 根据业务需求调整

# 2. 请求频率限制
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;

# 3. 防SQL注入过滤
access_by_lua_block {
    if ngx.re.match(body_data, [[\b(union|select|sleep)\b]]) then
        ngx.exit(403)
    end
}

生产环境注意事项

  1. 灰度发布时先开启 lua_code_cache off调试
  2. 使用 resty-cli工具进行热更新
  3. 压力测试推荐使用 wrk -t12 -c400 -d30s
  4. 重要业务建议采用双活架构设计
  5. 定期检查共享内存使用率(通过 ngx.shared.DICT.stats

标签:
  • Nginx
  • Lua
  • POST