如何使用 Lua 脚本实现负载均衡、请求转发和过滤功能
1. 基础的负载均衡脚本
圆形轮询算法
-- 定义上游服务器列表
local upstreams = {
"192.168.1.10:8080",
"192.168.1.11:8080",
"192.168.1.12:8080"
}
-- 使用 round-robin 算法
local function round_robin()
-- 获取计数器
local counter = ngx.shared.counter or 0
counter = (counter + 1) % #upstreams
ngx.shared.counter = counter
return upstreams[counter + 1]
end
带权重的圆形轮询算法
-- 根据权重选择服务器
local function weighted_round_robin()
local servers = {
{host = "192.168.1.10", weight = 5},
{host = "192.168.1.11", weight = 3},
{host = "192.168.1.12", weight = 2}
}
local total = 0
for _, server in ipairs(servers) do
total = total + server.weight
end
local rand = math.random(total)
local cur_weight = 0
for _, server in ipairs(servers) do
cur_weight = cur_weight + server.weight
if rand <= cur_weight then
return server.host
end
end
end
2. 请求转发和过滤
请求速率限制
-- 请求速率限制
local function limit_req()
local limit_key = ngx.var.binary_remote_addr
local limit_rate = 10 -- 每秒请求数限制
local current_calls = ngx.shared.limits:get(limit_key)
if current_calls and current_calls > limit_rate then
ngx.status = 429
ngx.say("Too Many Requests")
return ngx.exit(ngx.HTTP_TOO_MANY_REQUESTS)
end
-- 增加计数
local success, err = ngx.shared.limits:incr(limit_key, 1, 0, 1)
end
IP 黑白名单过滤
-- IP 黑白名单过滤
local function ip_filter()
local client_ip = ngx.var.remote_addr
local blacklist = {
"192.168.1.100",
"192.168.1.101"
}
for _, ip in ipairs(blacklist) do
if client_ip == ip then
ngx.status = 403
ngx.say("Forbidden")
return ngx.exit(ngx.HTTP_FORBIDDEN)
end
end
end
URL 路径过滤
-- URL 路径过滤
local function url_filter()
local uri = ngx.var.uri
local blocked_paths = {
"/admin",
"/internal"
}
for _, path in ipairs(blocked_paths) do
if string.find(uri, path) then
ngx.status = 403
ngx.say("Access Denied")
return ngx.exit(ngx.HTTP_FORBIDDEN)
end
end
end
3. 健康检查
local function health_check()
local http = require "resty.http"
local httpc = http.new()
local function check_server(host)
local ok, err = httpc:request_uri("http://" .. host .. "/health", {
method = "GET",
headers = {
["Host"] = "example.com"
}
})
if not ok then
return false
end
if ok.status == 200 then
return true
end
return false
end
-- 检查所有服务器
local healthy_servers = {}
for _, server in ipairs(upstreams) do
if check_server(server) then
table.insert(healthy_servers, server)
end
end
return healthy_servers
end
4. 完整的应用示例
-- 初始化共享内存
local shared = ngx.shared
shared.limits = shared.limits or {}
shared.counter = shared.counter or 0
-- 主处理函数
local function main()
-- 1. IP 过滤
ip_filter()
-- 2. URL 过滤
url_filter()
-- 3. 速率限制
limit_req()
-- 4. 获取健康服务器
local servers = health_check()
if #servers == 0 then
ngx.status = 503
ngx.say("No available servers")
return ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE)
end
-- 5. 负载均衡选择服务器
local target = round_robin()
-- 6. 转发请求
local httpc = require("resty.http").new()
local res, err = httpc:request_uri("http://" .. target .. ngx.var.uri, {
method = ngx.req.get_method(),
headers = ngx.req.get_headers(),
body = ngx.req.get_body_data()
})
if not res then
ngx.status = 502
ngx.say("Bad Gateway")
return ngx.exit(ngx.HTTP_BAD_GATEWAY)
end
-- 7. 返回响应
ngx.status = res.status
for k, v in pairs(res.headers) do
ngx.header[k] = v
end
ngx.say(res.body)
end
-- 执行
main()
这个脚本实现了:
- 多种负载均衡算法
- 请求速率限制
- IP 黑白名单过滤
- URL 路径过滤
- 服务器健康检查
- 请求转发处理
1万+

被折叠的 条评论
为什么被折叠?



