Nginx – proxy_module处理响应缓存流程

nginx作为反向代理时,经常会将上游服务器的响应缓存,以提升用户体验和服务并发能力。proxy_module提供了很多指令来完成这一项工作,下面简单分析下nginx在缓存上游响应时,大致的一个流程。

判断是否开启缓存

客户端的请求到来后,如果是HEAD请求会转成GET,这和cdn的做法是一样的,接着nginx会先根据proxy_cache指令来判断cache是否可用,如果指令结果为on,那么会接着判断proxy_cache_methods指令指定的请求方法是否与http_method匹配,如果没有匹配上则不使用缓存直接向上游发送请求并且不对响应缓存。

检查缓存

1 . 如果上一步判定此次请求使用缓存,那么nginx会先判断proxy_cache_bypass指令值决定哪些条件下即使缓存存在也不使用缓存,该指令可以指定多个变量,其中有一个不为空字符串或者0,都表示满足条件。

2. 接着nginx会根据proxy_cache_key生成对应的hash值,去共享内存中查找hash是否存在(其实每个key对应的hash都保存在二叉树中,而不是存在hash表中,可能数据经常删除新增,性能比hash表要强),如果不存在则直接向上游发送请求,然后对响应缓存(这里又涉及到一些判断,下面的步骤会说明)

3. 如果缓存存在,nginx会更新LRU链表,将hash对应在链表中的位置向链表头部移动。这里补充下,nginx在启动后一般会有额外的两个进程cache-loader和cache-manager,它们负责cache的载入和管理,举几个例子,在proxy_cache_path指令中可以指定cache-loader每次加载的cache文件数量和加载频率以及cache-manager淘汰旧缓存的频率;上面提到的LRU链表会交由cache-manager进程管理,它负责自动淘汰缓存;缓存都有有效期,cache-manager会定时去清除这些缓存。

判断缓存是否可用

上一步中如果缓存存在,nginx会接着判断缓存是否过期,如果已过期,则直接向上游发送新的请求,然后会判断proxy_cache_min_uses指令值(该指令表示对于同一个key,只有请求次数达到这个值后,才可以使用缓存,默认为1。使用缓存和缓存响应是不一样的)大于该值即将缓存响应给客户端,否则则会向上游发送请求。

接受上游响应

如果上面几步确定了使用缓存,但是由于某些条件没有使用缓存,而是直接向上游发送请求,那么在接收到上游响应后,nginx会根据一些条件决定如何更新或缓存响应。

响应头部

上游响应的头部,会影响nginx的缓存,比如以下几种:

X-Accel-Expires

值为正数则上游服务器明确表示,nginx可以缓存且指定了缓存的时间,负数为不缓存。

Set-Cookie

一般有Set-Cookie头部,nginx是不会缓存响应的。

Vary

一般有Vary头部,nginx也是不会缓存响应的。

Cache-Control

类似与cdn遵守的源站缓存策略,如果Cache-Control的值为private,max-age=0,no-cache,no-store,nginx都不会进行缓存。

以上头部都可以用proxy_ignore_headers指令忽略。

proxy_no_cache指令

如果配置了proxy_no_cache指令,在收到上游响应后,nginx不会缓存响应或者更新缓存。

proxy_cache_valid指令

如果响应码不匹配那么也不会缓存响应。

缓存上游响应

如果上一步中几个条件都满足,那么nginx就会决定缓存,nginx会将上游的响应先保存在临时文件中,然后做一次rename操作将临时文件移动到proxy_cahce_path指定的目录中,如果在用proxy_cache_path指令时指定了use_temp_path,那么要注意临时文件目录要和cache_path目录在同一个文件系统下,这样才可以直接使用rename,否则就是一次copy和删除了。

总结

其实nginx类似与cdn,可以用来做一个静态资源缓存服务器,cdn的回源相当于nginx向上游发送请求,cdn遵守源站的缓存策略,这和nginx对于上游响应头优先级最高的规则是相似的。不同的是proxy_module则提供了更多的指令来帮助用户完成更细粒度的缓存控制。

Leave a comment

电子邮件地址不会被公开。 必填项已用*标注