- config: 反向代理、缓存、负载均衡、安全、SSL 等配置模板 - lua: API 网关、认证、动态路由、限流、WebSocket 等脚本示例 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
160 lines
5.1 KiB
Nginx Configuration File
160 lines
5.1 KiB
Nginx Configuration File
# ============================================================
|
||
# Nginx Lua Caching Configuration
|
||
# ============================================================
|
||
#
|
||
# 功能说明:
|
||
# - 使用 Lua 共享字典缓存响应
|
||
# - 支持 TTL 过期和手动失效
|
||
# - X-Cache 头标识缓存命中状态
|
||
#
|
||
# 使用方式:
|
||
# lua_shared_dict response_cache 10m;
|
||
# content_by_lua_file /path/to/cache_handler.lua;
|
||
# ============================================================
|
||
|
||
http {
|
||
# 共享字典定义
|
||
lua_shared_dict response_cache 10m;
|
||
|
||
# 初始化 Lua 模块路径
|
||
lua_package_path "/path/to/lua/?.lua;;";
|
||
|
||
init_by_lua_block {
|
||
-- 全局配置
|
||
CACHE_DEFAULT_TTL = 60
|
||
}
|
||
|
||
server {
|
||
listen 80;
|
||
server_name cache.example.com;
|
||
|
||
# ---------- 缓存读取示例 ----------
|
||
location /api/data {
|
||
set $cache_key "api_data:$request_uri";
|
||
|
||
content_by_lua_block {
|
||
local handler = require "cache_handler"
|
||
local cache = ngx.shared.response_cache
|
||
|
||
local key = ngx.var.cache_key
|
||
local ttl = tonumber(ngx.var.arg_ttl) or CACHE_DEFAULT_TTL
|
||
|
||
-- 尝试缓存命中
|
||
local cached = cache:get(key)
|
||
if cached then
|
||
ngx.header["X-Cache"] = "HIT"
|
||
ngx.header["Content-Type"] = "application/json"
|
||
ngx.header["X-Cache-TTL"] = tostring(cache:ttl(key))
|
||
ngx.say(cached)
|
||
return
|
||
end
|
||
|
||
-- 缓存未命中,生成数据
|
||
local data = {
|
||
message = "fresh data",
|
||
timestamp = ngx.now(),
|
||
uri = ngx.var.request_uri,
|
||
}
|
||
|
||
local cjson = require "cjson.safe"
|
||
local json = cjson.encode(data)
|
||
|
||
-- 写入缓存
|
||
local ok, err, forcible = cache:set(key, json, ttl)
|
||
if not ok then
|
||
ngx.log(ngx.ERR, "cache set failed: ", err)
|
||
end
|
||
if forcible then
|
||
ngx.log(ngx.WARN, "cache LRU eviction triggered")
|
||
end
|
||
|
||
ngx.header["X-Cache"] = "MISS"
|
||
ngx.header["Content-Type"] = "application/json"
|
||
ngx.say(json)
|
||
}
|
||
}
|
||
|
||
# ---------- 使用外部 Lua 文件 ----------
|
||
location /api/handler {
|
||
set $cache_key "handler:$request_uri";
|
||
set $cache_ttl 120;
|
||
|
||
content_by_lua_file /path/to/lua/cache_handler.lua;
|
||
}
|
||
|
||
# ---------- 缓存失效:清除指定 key ----------
|
||
location /cache/purge {
|
||
content_by_lua_block {
|
||
if ngx.req.get_method() ~= "POST" then
|
||
ngx.status = 405
|
||
ngx.say('{"error": "method not allowed"}')
|
||
return
|
||
end
|
||
|
||
ngx.req.read_body()
|
||
local body = ngx.req.get_body_data()
|
||
if not body then
|
||
ngx.status = 400
|
||
ngx.say('{"error": "missing request body"}')
|
||
return
|
||
end
|
||
|
||
local cjson = require "cjson.safe"
|
||
local data = cjson.decode(body)
|
||
if not data or not data.key then
|
||
ngx.status = 400
|
||
ngx.say('{"error": "missing key field"}')
|
||
return
|
||
end
|
||
|
||
local cache = ngx.shared.response_cache
|
||
cache:delete(data.key)
|
||
|
||
ngx.header["Content-Type"] = "application/json"
|
||
ngx.say(cjson.encode({success = true, purged = data.key}))
|
||
}
|
||
}
|
||
|
||
# ---------- 缓存失效:清除全部 ----------
|
||
location /cache/purge_all {
|
||
# 仅允许本地访问
|
||
allow 127.0.0.1;
|
||
deny all;
|
||
|
||
content_by_lua_block {
|
||
if ngx.req.get_method() ~= "POST" then
|
||
ngx.status = 405
|
||
ngx.say('{"error": "method not allowed"}')
|
||
return
|
||
end
|
||
|
||
local cache = ngx.shared.response_cache
|
||
local count = cache:flush_all()
|
||
-- flush_all 标记所有 key 过期,flush_expired 实际清理
|
||
cache:flush_expired(0)
|
||
|
||
ngx.header["Content-Type"] = "application/json"
|
||
ngx.say('{"success": true, "action": "all keys invalidated"}')
|
||
}
|
||
}
|
||
|
||
# ---------- 缓存统计 ----------
|
||
location /cache/stats {
|
||
content_by_lua_block {
|
||
local cache = ngx.shared.response_cache
|
||
local keys = cache:get_keys(0) -- 0 = 不过滤过期 key
|
||
local cjson = require "cjson.safe"
|
||
|
||
local stats = {
|
||
capacity = cache:capacity(),
|
||
free_space = cache:free_space(),
|
||
key_count = #keys,
|
||
}
|
||
|
||
ngx.header["Content-Type"] = "application/json"
|
||
ngx.say(cjson.encode(stats))
|
||
}
|
||
}
|
||
}
|
||
}
|