1

Nginx proxy_cache

 2 years ago
source link: https://fann.im/blog/2014/08/30/nginx-proxy-cache/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Nginx proxy_cache

Aug 30, 2014

Nginx proxy_cache 可以将后端动态请求的返回内容进行缓存,原理是 URL 作为 cache_key,将内容缓存到磁盘,新请求符合缓存规则的话直接读取缓存内容返回。

proxy_cache_path /tmp/ngx_cache/proxy_cache_dir levels=1:2 keys_zone=ngx_cache:10m inactive=30m max_size=500m;
proxy_temp_path  /tmp/ngx_cache/proxy_temp_dir;

server {
    proxy_cache ngx_cache;
    proxy_cache_valid 10m;
    add_header  Nginx-Cache "$upstream_cache_status";

    set $no_cache '';
    set_by_lua $cache_key "
        local no_cache = false
        if ngx.var.http_cookie and string.find(ngx.var.http_cookie, 'user') then
            # 带 cookie 的请求(比如登录用户)忽略缓存
            no_cache = true
        end

        if ngx.var.uri == '/api/test' then
        	  #某些 URL 的请求强制缓存,不管是否有 cookie
            no_cache = false
        end

        if no_cache then
            #确定忽略缓存就不再计算 cache_key
            ngx.var.no_cache = 'true'

            return ngx.var.uri
        end

        local uri_args = ngx.req.get_uri_args()
        local args = {}
        for k, v in pairs(uri_args) do
            if k and v and type(v) == 'string' then
                if k == 'count' or k == 'sort' or k == 'page' then
                    #过滤掉非法请求参数
                    args[#args+1] = k .. '=' .. v
                end
            end
        end

        if #args > 0 then
            table.sort(args)
            return ngx.var.uri .. '?' .. table.concat(args, '&')
        else
            return ngx.var.uri
        end
    ";
    
    proxy_cache_key $cache_key;
    proxy_no_cache $no_cache;
    proxy_cache_bypass $no_cache;
    
    location / {
	     proxy_pass http://localhost:8080;
    }
}

配置 proxy_cache 很简单,建议先通读 NGINX Content Caching 文档。记几点笔记:

  1. 用 OpenResty(ngx_lua) 作为前端 Nginx 代理和缓存服务器,好处是可以用 set_by_lua 计算赋值变量,原生 set 语法不够灵活。
  2. proxy_cache_path 指定缓存文件目录,和 proxy_temp_path 最好设置在同一文件分区下,缓存内容是先写在 temp_path,然后移动到 cache_path,不同文件分区会影响性能。
  3. keys_zone 命名并设置缓存的内存空间大小,要注意的是这个内存空间并不保存缓存文件,而是缓存文件的元信息(meta information),所以不必太大,根据文档 1M 大小可保存 8000 文件的元信息,可以根据缓存文件数量进行设置。
  4. inactive=30m 表示 30 分钟没有被访问的文件会被 cache manager 删除,max_size=500m 表示缓存目录最大限制 500M 磁盘空间。
  5. proxy_cache 指明用哪个缓存空间,proxy_cache_valid 是缓存的有效时间,可以针对不同响应状态设置不同的有效时间,比如 proxy_cache_valid 404 1m;,默认只对 200/301/302 响应进行缓存。
  6. 缓存文件数量过多会影响 proxy_cache 性能,Nginx 在启动时 cache manager 会检查并读取缓存文件的元信息到内存,这个读取是有限制的,默认情况下 cache manager 每次读取 100 个文件的元信息,每次读取限时 200ms,间隔 50ms 进行下次读取。
  7. 缓存文件并不是越多越好,所以 cache_key 的设计非常关键。代理或 URL 跳转常常会添加的无用请求参数,这就会出现不同的 cache_key 保存了多份相同的缓存内容,这对缓存效果影响很大。通过 ngx_lua 可以对 URL 参数进行过滤,保证 cache_key 唯一。
  8. table.sort(args) 对 URL 参数重排序,避免 /api?page=1&count=10 /api?count=10&page=1 生成两份缓存的情况。
  9. $upstream_cache_status 可以获取缓存状态,包括 HIT/BYPASS/MISS/EXPIRED,可以记录到 access_log 和 response header,用以计算缓存命中率。
  10. proxy_no_cache 如果有值且不为 ‘0’,该请求的 response 就不会生成缓存。
  11. proxy_cache_bypass 如有有值且不为 ‘0’,该请求会忽略缓存。
  12. proxy_cache 不支持手动清除缓存,可以通过第三方模块 ngx_cache_purge 来清除指定 URL 的缓存。

proxy_cache 非常的简单高效,合理使用可以有效的减轻后端服务压力,提升服务访问速度。

Was this page helpful?


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK