lolly/docs/config/lua/shared-dict.conf
xfy 6543422281 docs: 添加 Nginx 配置和 Lua 脚本示例文档
- config: 反向代理、缓存、负载均衡、安全、SSL 等配置模板
- lua: API 网关、认证、动态路由、限流、WebSocket 等脚本示例

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 17:59:22 +08:00

239 lines
7.7 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ============================================================
# Nginx lua_shared_dict 共享字典配置示例
# ============================================================
#
# 功能说明:
# - 跨请求共享数据
# - 实现缓存、计数器、限流
# - 进程间通信
#
# Lolly 对应配置:
# lolly 内置 Lua 沙箱,支持共享字典功能
# 相关文档: docs/lua-nginx-module/05-shdict.md
# ============================================================
http {
# 定义共享字典
# lua_shared_dict name size;
# size: 内存大小,支持 k, m 单位
lua_shared_dict cache 10m; # 缓存存储
lua_shared_dict rate_limit 5m; # 限流计数
lua_shared_dict sessions 10m; # 会话存储
lua_shared_dict config 1m; # 配置存储
server {
listen 80;
server_name shdict.example.com;
# 缓存示例
location /api/cached {
content_by_lua_block {
local cjson = require "cjson.safe"
local cache = ngx.shared.cache
local key = ngx.var.arg_key or "default"
-- 尝试从缓存获取
local value, flags = cache:get(key)
if value then
ngx.header["X-Cache"] = "HIT"
ngx.say(value)
return
end
-- 生成数据(模拟)
local data = {
key = key,
value = "generated_value_" .. key,
timestamp = ngx.now()
}
local json = cjson.encode(data)
-- 存入缓存60 秒过期
local success, err, forcible = cache:set(key, json, 60)
if not success then
ngx.log(ngx.WARN, "failed to set cache: ", err)
end
-- 检查是否 LRU 强制淘汰
if forcible then
ngx.log(ngx.WARN, "cache LRU eviction occurred")
end
ngx.header["X-Cache"] = "MISS"
ngx.say(json)
}
}
# 限流示例
location /api/limited {
access_by_lua_block {
local limit = ngx.shared.rate_limit
local ip = ngx.var.remote_addr
local key = "limit:" .. ip
-- 获取当前计数
local count, err = limit:incr(key, 1, 0, 60) # 60 秒窗口
if not count then
ngx.log(ngx.ERR, "failed to incr: ", err)
count = 0
end
-- 设置过期时间(仅首次)
if count == 1 then
limit:expire(key, 60)
end
-- 检查限制
local max_requests = 100
if count > max_requests then
ngx.status = 429
ngx.header["X-RateLimit-Limit"] = max_requests
ngx.header["X-RateLimit-Remaining"] = 0
ngx.header["X-RateLimit-Reset"] = 60
ngx.say('{"error": "Rate limit exceeded"}')
ngx.exit(429)
end
-- 设置响应头
ngx.header["X-RateLimit-Limit"] = max_requests
ngx.header["X-RateLimit-Remaining"] = math.max(0, max_requests - count)
}
content_by_lua_block {
ngx.say('{"status": "ok"}')
}
}
# 会话存储示例
location /api/session {
content_by_lua_block {
local cjson = require "cjson.safe"
local sessions = ngx.shared.sessions
local session_id = ngx.var.cookie_session_id
if ngx.req.get_method() == "GET" then
-- 获取会话
if not session_id then
ngx.status = 401
ngx.say('{"error": "No session"}')
ngx.exit(401)
end
local session_data = sessions:get("session:" .. session_id)
if not session_data then
ngx.status = 401
ngx.say('{"error": "Session expired"}')
ngx.exit(401)
end
ngx.say(session_data)
elseif ngx.req.get_method() == "POST" then
-- 创建会话
ngx.req.read_body()
local data = cjson.decode(ngx.req.get_body_data())
-- 生成 session ID
local session_id = ngx.md5(ngx.now() .. math.random())
-- 存储会话30 分钟过期
sessions:set("session:" .. session_id, cjson.encode(data), 1800)
-- 设置 Cookie
ngx.header["Set-Cookie"] = "session_id=" .. session_id .. "; Path=/; HttpOnly"
ngx.say(cjson.encode({session_id = session_id}))
end
}
}
# 配置管理示例
location /admin/config {
content_by_lua_block {
local cjson = require "cjson.safe"
local config = ngx.shared.config
local method = ngx.req.get_method()
if method == "GET" then
local keys = config:get_keys()
local result = {}
for _, key in ipairs(keys) do
result[key] = config:get(key)
end
ngx.say(cjson.encode(result))
elseif method == "POST" then
ngx.req.read_body()
local data = cjson.decode(ngx.req.get_body_data())
for k, v in pairs(data) do
config:set(k, v)
end
ngx.say(cjson.encode({success = true}))
end
}
}
# 统计信息
location /admin/stats {
content_by_lua_block {
local cjson = require "cjson.safe"
local function get_stats(dict_name)
local dict = ngx.shared[dict_name]
return {
capacity = dict:capacity(),
free_space = dict:free_space(),
keys = #dict:get_keys()
}
end
local stats = {
cache = get_stats("cache"),
rate_limit = get_stats("rate_limit"),
sessions = get_stats("sessions"),
config = get_stats("config")
}
ngx.header["Content-Type"] = "application/json"
ngx.say(cjson.encode(stats))
}
}
}
}
# lua_shared_dict API 说明:
#
# 1. 基础操作:
# - get(key): 获取值
# - set(key, value, exptime?, flags?): 设置值
# - add(key, value, exptime?, flags?): 仅当 key 不存在时设置
# - replace(key, value, exptime?, flags?): 仅当 key 存在时替换
# - delete(key): 删除
#
# 2. 计数操作:
# - incr(key, value?, init?, init_ttl?): 增加
# - decr(key, value?): 减少
# - flush_all(): 清空所有
# - flush_expired(max_count?): 清理过期
#
# 3. 过期管理:
# - expire(key, exptime): 设置过期时间
# - ttl(key): 获取剩余过期时间
#
# 4. 统计:
# - capacity(): 总容量(字节)
# - free_space(): 剩余空间(字节)
# - get_keys(max_count?): 获取所有 key
#
# 5. 特点:
# - 所有 worker 共享
# - LRU 淘汰策略
# - 原子操作
# - 支持过期时间