# ============================================================ # Nginx balancer_by_lua 动态负载均衡配置示例 # ============================================================ # # 功能说明: # - 使用 Lua 实现动态负载均衡 # - 服务发现集成 # - 健康检查 # # Lolly 对应配置: # 可通过 Lua 实现自定义负载均衡逻辑 # 相关文档: docs/lua-nginx-module/08-balancer.md # ============================================================ http { lua_shared_dict upstream_list 10m; lua_shared_dict health_status 5m; # 初始化上游服务器列表 init_by_lua_block { local upstream_list = ngx.shared.upstream_list -- 初始服务器列表 local servers = { {host = "backend1", port = 8080, weight = 3}, {host = "backend2", port = 8080, weight = 2}, {host = "backend3", port = 8080, weight = 1}, } -- 存储到共享字典 local cjson = require "cjson.safe" upstream_list:set("api_servers", cjson.encode(servers)) } # 后台健康检查 init_worker_by_lua_block { local health = require "health_checker" -- 每 10 秒检查一次 local function check_health(premature) if premature then return end local upstream_list = ngx.shared.upstream_list local health_status = ngx.shared.health_status local cjson = require "cjson.safe" local servers_raw = upstream_list:get("api_servers") local servers = cjson.decode(servers_raw) for _, server in ipairs(servers) do local key = server.host .. ":" .. server.port -- 发送健康检查请求(使用 cosocket) local ok = health.check(server.host, server.port) health_status:set(key, ok and "healthy" or "unhealthy") end -- 递归调度下次检查 ngx.timer.every(10, check_health) end -- 启动定时器 ngx.timer.at(0, check_health) } # 定义上游 upstream dynamic_backend { server 0.0.0.1; # 占位符,实际由 balancer_by_lua 选择 balancer_by_lua_block { local balancer = require "ngx.balancer" local upstream_list = ngx.shared.upstream_list local health_status = ngx.shared.health_status local cjson = require "cjson.safe" -- 获取服务器列表 local servers_raw = upstream_list:get("api_servers") local servers = cjson.decode(servers_raw) -- 过滤健康服务器 local healthy_servers = {} for _, server in ipairs(servers) do local key = server.host .. ":" .. server.port if health_status:get(key) == "healthy" then -- 根据权重添加多次 for _ = 1, server.weight do table.insert(healthy_servers, server) end end end if #healthy_servers == 0 then ngx.log(ngx.ERR, "No healthy servers available") return ngx.exit(503) end -- 轮询选择(可替换为其他算法) local idx = ngx.var.request_id:byte(1) % #healthy_servers + 1 local selected = healthy_servers[idx] -- 设置当前请求的上游 local ok, err = balancer.set_current_peer(selected.host, selected.port) if not ok then ngx.log(ngx.ERR, "failed to set peer: ", err) return ngx.exit(500) end } } server { listen 80; server_name balancer-lua.example.com; location /api { proxy_pass http://dynamic_backend; proxy_set_header Host $host; } # 动态更新服务器列表 API location /admin/servers { content_by_lua_block { local cjson = require "cjson.safe" local upstream_list = ngx.shared.upstream_list local method = ngx.req.get_method() if method == "GET" then local servers = upstream_list:get("api_servers") ngx.header["Content-Type"] = "application/json" ngx.say(servers) elseif method == "POST" then ngx.req.read_body() local data = cjson.decode(ngx.req.get_body_data()) -- 验证数据格式 if not data or not data.servers then ngx.status = 400 ngx.say(cjson.encode({error = "Invalid data"})) ngx.exit(400) end upstream_list:set("api_servers", cjson.encode(data.servers)) ngx.say(cjson.encode({success = true})) else ngx.status = 405 ngx.say(cjson.encode({error = "Method not allowed"})) end } } } } # balancer_by_lua 说明: # # 1. 核心功能: # - 动态选择上游服务器 # - 支持自定义负载均衡算法 # - 集成服务发现 # # 2. ngx.balancer API: # - set_current_peer(host, port): 设置目标服务器 # - set_more_tries(count): 设置重试次数 # - get_last_failure(): 获取上次失败信息 # # 3. 使用场景: # - 动态服务发现(Consul、etcd) # - 基于权重的负载均衡 # - 基于延迟的路由 # - A/B 测试流量分发 # # 4. 注意事项: # - 需要占位符 server 指令 # - 健康检查需要自行实现 # - 使用 cosocket 避免阻塞