web 应用业务缓存通常3级:

一级缓存:JVM 本地缓存
二级缓存:Redis集中式缓存
三级缓存:Nginx Proxy Cache 缓存 或 Nginx Lua 缓存
四级缓存:静态资源CDN缓存 页面静态化
本文主要分享 Nginx Lua 缓存配置开发
鉴于 Nginx Proxy Cache 缓存的劣势,在生产项目中很少使用,如果真正要体现出在距离用户最近的位置设置缓存,需要使用 Nginx Lua 缓存,才能发挥出缓存的优势。
Lua 脚本语言出现前,需要使用 c 或 c++ 语言开发Nginx功能,难度大,风险高。Nginx和Lua集成后,可以通过 Lua 脚本配置 Nignx 。
协程机制:
Lua 的协程机制 类似于 Nginx 的协程机制。
所以Nginx协程相比于 JVM的 servlet的多线程机制更高效。
Nginx 生命周期11个处理阶段
可以在 Nginx 的生命周期过程中,添加 Lua 控制功能,实现对Nginx功能的配置。
NGX_HTTP_POST_READ_PHASE = 0 // 读取请求头
NGX_HTTP_SERVER_REWRITE_PHASE = 0 // 执行 uri rewrite rewrite_handler
NGX_HTTP_FIND_CONFIG_PHASE // 根据 uri 替换 location
NGX_HTTP_REWRITE_PHASE // 根据替换结果继续执行 rewrite rewrite_handler
NGX_HTTP_POST_REWRITE_PHASE // 执行 rewrite 后处理
NGX_HTTP_PREACCESS_PHASE // 可以用于处理限流场景
// 认证预处理 请求限制(limit_req_handler) 连接限制(limit_conn_handler)
NGX_HTTP_ACCESS_PHASE // 可用于处理 token 的场景
// 认证处理 auth_basic_handler access_handler
NGX_HTTP_POST_ACCESS_PHASE // 认证后处理 认证不通过 丢包
NGX_HTTP_TRY_FILES_PHASE // 深度 try 标签
NGX_HTTP_CONTENT_PHASE // 内容处理 static_handler
NGX_HTTP_LOG_PHASE // 日志处理 log_handler
init_by_lua 系统启动时调用
init_worker_by_lua worker进程启动时调用
set_by_lua nginx变量使用复杂 lua return
rewrite_by_lua 重写 url 规则
access_by_lua 权限验证阶段
content_by_lua 内容输出阶段(使用较多)
OpenResty 的优势:
OpenResty 可以通过 shared dic 共享内存字典,实现远超过 proxy cache 性能的缓存,因为 shared dic 对所有 worker 进程都可见,并加成了 LRU 淘汰规则。再加上 OpenResty 对 Redis 的支持,可以实现更高性能的三级缓存。
nginx.conf
...
# 配置 shared dictionary 的扩展,声明128m的内存承载共享字典访问
lua_shared_dict lua_cache 128m;
...
server {
...
# 设置location用来做访问shared dict的lua文件
location /luadetail/get {
default_type "application/json";
content_by_lua_file ../lua/sharedis.lua
...
sharedis.lua
local args = ngx.req.get_uri_args()
local id = args["id"]
local redis = require "resty.redis"
local cache = redis:new()
local ok,err = cache:connect("172.16.16.16", 6379)
local product = cache:get("product_"..id)
if product == ngx.null or product == nil then
local resp = ngx.location.capture("/product/get?id="..id)
product = resp.body
end
ngx.say(product)
显然,Nginx 缓存直接读取 Redis 中的数据既能保证高效率,也不需要关心缓存中数据的更新失效策略,相比于使用 Nginx 服务器内存作缓存载体更高效。