ngx_lua灵活定制fastcgi_cache缓存key
Web开发常见的几种缓存
- 常用缓存(memcached和redis)
- Nginx的缓存(标准模块缓存: proxy_cache和fastcgi_cache / 第三方模块做缓存: ngx_lua)
- CDN缓存
- 浏览器缓存(Cache-Control和LocalStorage)
proxy_cache和fastcgi_cache
proxy_cache和fastcgi_cache都为Nginx的内置缓存,proxy_cache主要用于反向代理时,对后端内容源服务器进行缓存,fastcgi_cache主要用于对FastCGI的动态程序进行缓存。
两者相关配置类似,以下为fastcgi_cache举例
原理
针对fastcgi(如:php-fpm)返回的内容缓存为静态文件(文件名是用Md5算法对Key进行哈希后所得,而Key可使用fastcgi_cache的相关指令来进行控制)
,在用户浏览时,无需重复请求后端fastcgi,而直接返回缓存的内容,减少了后端的语言解析以及数据库连接的消耗。
数据流程图
指令注释
nginx的http作用域:
fastcgi_cache_path /home/wwwroot/yii.me/runtime/logs levels=1:2 keys_zone=keys_zone=zone:512m:1m inactive=1d
max_size=1g; #指定一个路径,目录结构等级,关键字区域存储时间和非活动删除时间。以及最大占用空间(keys_zone主要缓存key和文件元信息,不会缓存页面)
nginx的location作用域:
fastcgi_cache zone; #表示开启FastCGI缓存并为其指定一个名称:zone
fastcgi_cache_valid 1m; #设置缓存时间1分钟
fastcgi_cache_min_uses 1; #设置链接请求1次就被缓存
fastcgi_cache_use_stale error timeout invalid_header http_500; #定义哪些情况下用过期缓存(如果对实效要求不高建议加updating,关闭fastcgi_cache_lock,可提高性能)
fastcgi_cache_methods GET POST; #缓存GET和POST请求
fastcgi_cache_key “$cache_path$containerid$containerpage”; #缓存key=页面+containerid+分页页码
fastcgi_ignore_headers Cache-Control Expires Set-Cookie; #包含这些header的响应不缓存
fastcgi_cache_lock on; #同时有请求处理的时候只有一个请求允许访问后端服务器,其余请求等待缓存结果或等待超时再进行响应
fastcgi_cache_lock_timeout 5s; #等待超时时间5秒,超时则穿透,且不缓存穿透结果
fastcgi_cache_bypass $skip_cache; #非0不从cache中取
fastcgi_no_cache $skip_cache; #非0不保存到cache
性能提升
以下测试使用的vps机器
ab -c10 -n50000 http://127.0.0.1:8080/echo.php
- fastcgi_cache off Requests per second: 2441.56 [#/sec] (mean)
- fastcgi_cache zone Requests per second: 3662.79 [#/sec] (mean)
ngx_lua模块
参考资料
- OpenResty 最佳实践-子查询
- OpenResty 最佳实践-缓存
在ngx_lua模块中使用共享内存
- 定义一个共享内存对象
语法:lua_shared_dict
该命令主要是定义一块名为name的共享内存空间,内存大小为size。通过该命令定义的共享内存对象对于Nginx中所有worker进程都是可见的,当Nginx通过reload命令重启时,共享内存字典项会从新获取它的内容,而当Nginx
退出时,字典项的值将会丢失。
例子:1234567891011121314151617181920212223242526272829303132333435363738394041424344location /testngxlua {default_type application/json;charset utf8;access_by_lua 'function get_from_cache(key)local cache_ngx = ngx.shared.my_cachelocal value = cache_ngx:get(key)return valueendfunction set_to_cache(key, value, exptime)if not exptime thenexptime = 0endlocal cache_ngx = ngx.shared.my_cachelocal succ, err, forcible = cache_ngx:set(key, value, exptime)return succendngx.req.read_body()local c = ngx.req.get_uri_args()["c"] or ""local str = get_from_cache(c)if (str ~= nil) thenngx.print("ngx_cache: "..str)elselocal options = {}options["method"] = ngx.var.request_method == "GET" and ngx.HTTP_GET or ngx.HTTP_POSToptions["body"] = ngx.var.request_bodyoptions["args"] = ngx.var.argslocal res = ngx.location.capture("/index.php"..ngx.var.uri, options)if res.status == 200 thenset_to_cache(c, res.body, 300)ngx.print(res.body)elsengx.say(res.status)endend';}