点赞
评论
收藏
分享
举报
NGINX缓存原理及源码分析(二)
发表于2021-01-18 14:28

浏览 2.7k

概述

上篇我们讲述了NGINX缓存的原理以及NGINXCache LoaderCache Manager进程是如何工作的。本篇,我们继续分析NGINX工作原理的剩余的两个部分,那就是NGINX是如何生成和使用缓存的。

引用上篇文章中的图片来描述从高层次来看,NGINX缓存的大体结构。

如上图所示,NGINX在内存中维护一棵红黑树,然后每一个节点上存储这文件的元数据(meta data),并且在磁盘中存放文件的完整内容。

NGINX的缓存功能都是围绕上述数据结构进行的。主要包括以下四个任务:

1.     维护

保存上图数据的一致性,比如相应缓存文件已经对应的内存数据进行删除。

2.     加载

NGINX启动时,如果磁盘中存在缓存文件,则需要生成对应内存中的元数据。

3.     生成

创建Memory中的元数据以及对应的磁盘中的文件。

4.     使用

新的请求到来时,如果对应的location匹配有cache,判断cache是否存在已经是否可用,如果可用,则直接返回对应磁盘中的文件。

本篇文章,我们要分析34的工作原理和流程。

配置指令

NGINX提供了如下众多配置选项来控制NGINX缓存的生成和使用。

buffer工作有关指令

如果不配置proxy_bufferingNGINX是不能生产缓存的,所以我们先来分析buffering的工作原理。

buffer工作原理

首先第一个概念是所有的这些proxy buffer参数是作用到每一个请求的。每一个请求会安按照参数的配置获得自己的bufferproxy buffer不是global而是per request的。

proxy_buffering 是为了开启response buffering of the proxied server,开启后proxy_buffersproxy_busy_buffers_size参数才会起作用。
无论proxy_buffering是否开启,proxy_buffer_size都是工作的,proxy_buffer_size所设置的buffer_size的作用是用来存储upstreamresponseheader

proxy_buffering 开启的情况下,NGINX将会尽可能的读取所有的upstream端传输的数据到buffer,直到proxy_buffers设置的所有buffer们被写满或者数据被读取完(EOF)。此时NGINX开始向客户端传输数据,会同时传输这一整串buffer们。同时如果响应的内容很大的话,NGINX会接收并把他们写入到临时文件里去。大小由proxy_max_temp_file_size控制。如果busybuffer传输完了会从temp_file里面接着读数据,直到传输完毕。一旦proxy_buffers设置的buffer被写入,直到buffer里面的数据被完整的传输完(传输到客户端),这个buffer将会一直处在busy状态,我们不能对这个buffer进行任何别的操作。所有处在busy状态的buffer size加起来不能超过proxy_busy_buffers_size,所以proxy_busy_buffers_size是用来控制同时传输到客户端的buffer数量的。

相关指令

Syntax:proxy_buffering on | off;

Default:proxy_buffering on;

Context:http, server, location

启用或禁用使用缓冲区来存储代理服务器的响应。默认打开,如果proxy_buffering关闭,则NGINX不会生成缓存文件。启用后,NGINX会尽快从代理服务器收到响应,并将其保存到由指令proxy_buffer_sizeproxy_buffers指令设置的缓冲区中 。如果缓冲区不能容纳整个响应,则可以将一部分响应保存到磁盘上的临时文件中。临时文件大小由 proxy_max_temp_file_sizeproxy_temp_file_write_size 指令配置。指令proxy_temp_file_write_size定义的是一次访问能写入的临时文件的大小,默认是proxy_buffer_sizeproxy_buffers中设置的缓冲区大小的2倍,Linux下一般是8k。指令proxy_max_temp_file_size指定当响应内容大于proxy_buffers指定的缓冲区时, 写入硬盘的临时文件的大小. 如果超过了这个值, NGINX将与Proxy服务器同步的传递内容, 而不再缓冲到硬盘. 设置为0, 则直接关闭硬盘缓冲。

禁用后,收到响应后到就立即同步传递到客户端。NGINX不会尝试从代理服务器读取整个响应。一次可以从服务器接收的最大数据大小由proxy_buffer_size指令设置。

可以通过在“ X-Accel-Buffering”响应头字段中传递“ yes”“ no” 来启用或禁用缓冲。也可以使用proxy_ignore_headers指令禁用此功能 

Syntax:proxy_buffer_size size;

Default:proxy_buffer_size 4k|8k;

Context:http, server, location

设置从代理服务器接收响应头的缓冲区大小。默认情况下,缓冲区大小等于系统一个内存页面大小。根据平台的不同,它可以是4K8K。当然,也可以设置的比4K或者8K小。

Syntax:proxy_buffers number size;

Default:proxy_buffers 8 4k|8k;

Context:http, server, location

设置用于为单个客户连接从代理服务器读取响应的缓冲区的数量和单个缓存的大小。proxy_buffers的缓冲区大小一般会设置的比较大,以应付大网页。 proxy_buffers当中单个缓冲区的大小是由系统的内存页面大小决定的,Linux系统中一般为4k proxy_buffers由缓冲区数量和缓冲区大小组成的。总的大小为number*size

若某些请求的响应过大,则超过_buffers的部分将被缓冲到硬盘(缓冲目录由_temp_path指令指定), 当然这将会使读取响应的速度减慢, 影响用户体验. 可以使用proxy_max_temp_file_size指令关闭磁盘缓冲。

Syntax:proxy_busy_buffers_size size;

Default:proxy_busy_buffers_size 8k|16k;

Context:http, server, location

参数proxy_busy_buffers_size不是独立的空间,它是proxy_buffersproxy_buffer_size的一部分。NGINX会在没有完全读完后端响应的时候就开始向客户端传送数据,所以它会划出一部分缓冲区来专门向客户端传送数据(这部分的大小是由proxy_busy_buffers_size来配置的,建议为proxy_buffers中单个缓冲区大小的2倍,比如8K),然后它继续从后端取数据,缓冲区满了之后就写到磁盘的临时文件中。

NGINX缓存生成和使用有关指令

Syntax:proxy_cache_background_update on | off;

Default:proxy_cache_background_update off;

Context:http, server, location

允许在后台发送子请求来更新过期的缓存文件。一般一个请求过来判断一下缓存时间,如果过期了再从后端取

Syntax:proxy_cache_bypass string ...;

Default:—

Context:http, server, location

类似于proxy_no_cache,但是,其控制什么情况不使用缓存的内容,而是直接到后端获取最新的内容。如果命中,则$upstream_cache_statusBYPASS,而且响应内容会再被缓存。可以与proxy_no_cache指令一起使用。

Proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;

proxy_cache_bypass $http_pragma  $http_authorization;  

Syntax:proxy_cache_convert_head on | off;

Default:proxy_cache_convert_head on;

Context:http, server, location

启用或禁用将“ HEAD”方法转换为“ GET”进行缓存。禁用转换后, 应将缓存键配置为包括$request_method

Syntax:proxy_cache_lock on | off;

Default:proxy_cache_lock off;

Context:http, server, location

当多个客户端同时请求同一份内容时,如果开启proxy_cache_lock(默认off),则只有一个请求被发送至后端。其他请求将等待该请求的返回。当第一个请求返回后,其他相同请求将从缓存中获取内容返回。当第一个请求超过了proxy_cache_lock_timeout超时时间(默认为5s),则其他请求将同时请求到后端来获取响应,且响应不会被缓存(在1.7.8版本之前是被缓存的)。启用proxy_cache_lock可以应对Dog-pile effect(当某个缓存失效时,同时有大量相同的请求没命中缓存,而同时请求到后端,从而导致后端压力太大,此时限制一个请求去拿即可)。

Syntax:proxy_cache_max_range_offset number;

Default:—

Context:http, server, location

指令是在1.11.6版本中引入的。设置字节范围请求的字节偏移量。如果范围超出偏移量,则范围请求将传递到代理服务器,并且不会缓存响应。

Syntax:proxy_cache_methods GET | HEAD | POST …;

Default:proxy_cache_methods GET HEAD;

Context:http, server, location

设置为哪些客户端请求类型进行缓存。默认值是GETHEAD方法。

Syntax:proxy_cache_min_uses number;

Default:proxy_cache_min_uses 1;

Context:http, server, location

为在缓存响应之前,相同文件请求的最小次数。再达到此数值之前,响应不会被缓存。

Syntax:     proxy_cache_revalidate on | off;

Default:     proxy_cache_revalidate off;

Context:     http, server, location

当缓存过期后,如果开启了proxy_cache_revalidate,则会发出一次if-modified-sinceif-none-match条件请求到后端服务器,如果后端返回304,并且使用本地缓存响应客户请求。此时$upstream_cache_statusREVALIDATED,这样可以节省带宽和减少写磁盘的次数

Syntax:proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | http_429 | off ...;

Default:proxy_cache_use_stale off;

Context:http, server, location

当对缓存内容的过期时间不敏感,或者后端服务出问题时,即使缓存的内容不新鲜也总比返回错误给用户强(类似于托底),此时可以配置该参数,如“proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504”,即如果出现超时、后端连接出错、500502503等错误时,则即使缓存内容已过期也先返回给用户,此时$upstream_cache_statusSTALE。还有一个updating表示缓存已过期但正在被别的NGINX Worker进程更新,但先返回了过期内容,此时$upstream_cache_statusUPDATING

参数error可以在无法选取有效后端服务处理当前请求的情况下使用过期缓存。参数update允许当前缓存在更新的时候使用过期缓存。这样可以减少在缓存更新时对后端服务器的访问次数。

如果收到的客户端HTTP协议的头部的Cache-Control字段包含某些参数,NGINX也可以使用过期缓存来响应客户端请求。这个条件的优先级低于指令配置的参数。

参数“stale-while-revalidate”: 在缓存更新时可以使用过期缓存。参数“stale-if-error:在出现错误时可以使用缓存。

确定在与代理服务器通信期间可以在哪些情况下使用过时的缓存响应。该指令的参数与 proxy_next_upstream 指令的参数匹配。

如果无法选择代理服务器来处理请求,则 error 参数还允许使用过时的缓存响应。此外,如果当前正在更新,则 updating 参数允许使用过时的缓存响应。这允许在更新缓存数据时最大化减少对代理服务器的访问次数。也可以直接在响应头中指定响应失效多少秒数后直接启用过时的缓存响应(1.11.10)。这比使用指令参数的优先级低。

Cache-Control 头字段的 stale-while-revalidate 扩展允许使用过时的缓存响应(如果当前正在更新)。

Cache-Control 头字段的 stale-if-error 扩展允许在出现错误时使用过时的缓存响应。

要在填充新缓存元素时最大化减少对代理服务器的访问次数,可以使用 proxy_cache_lock 指令。

Syntax:proxy_cache_lock on | off;

Default:proxy_cache_lock off;

Context:http, server, location

当多个客户端同时请求同一份内容时,如果开启proxy_cache_lock(默认off),则只有一个请求被发送至后端。其他请求将等待该请求的返回。当第一个请求返回后,其他相同请求将从缓存中获取内容返回。当第一个请求超过了proxy_cache_lock_timeout超时时间(默认为5s),则其他请求将同时请求到后端来获取响应,且响应不会被缓存(在1.7.8版本之前是被缓存的)。启用proxy_cache_lock可以应对Dog-pile effect(当某个缓存失效时,同时有大量相同的请求没命中缓存,而同时请求到后端,从而导致后端压力太大,此时限制一个请求去拿即可)。

Syntax:proxy_cache_lock_age time;

Default:proxy_cache_lock_age 5s;

Context:http, server, location

指令proxy_cache_lock_age1.7.8新添加的,如果在proxy_cache_lock_age指定的时间内(默认为5s),最后一个发送到后端进行新缓存构建的请求还没有完成,则下一个请求将被发送到后端来构建缓存(因为1.7.8版本之后,proxy_cache_lock_timeout超时之后返回的内容是不缓存的,需要下一次请求来构建响应缓存)。

Syntax:proxy_cache_lock_timeout time;

Default:proxy_cache_lock_timeout 5s;

Context:http, server, location

设置proxy_cache_lock的过期时间。当timer过期,请求会被发向后端服务器,但是,服务器的响应不会被缓存。在1.7.8版本之前,这种请求的响应也会被缓存。

Syntax:proxy_cache_valid [code ...] time;

Default:—

Context:http, server, location

为不同的响应代码设置缓存时间。例如以下指令

proxy_cache_valid 200 302 10m;

proxy_cache_valid 404      1m;

为代码为 200 302 的响应设置 10 分钟的缓存时间,为代码 404 的响应设置 1 分钟的缓存时间。

如果仅指定了缓存时长比如proxy_cache_valid 5m;将只缓存 200301 302 的响应。

此外,可以指定 any 参数来缓存任何响应:

proxy_cache_valid 200 302 10m;

proxy_cache_valid 301      1h;

proxy_cache_valid any      1m;

也可以直接在响应头中设置缓存的参数。这比使用该指令设置缓存时间具有更高的优先级。X-Accel-Expires 头字段设置以秒为单位的响应缓存时间。零值将禁用响应缓存。如果值以 @ 前缀开头,则设置自 Epoch 以来的绝对时间(以秒为单位)内的响应可以被缓存。如果头不包括 X-Accel-Expires 字段,则可以在头字段 Expires Cache-Control 中设置缓存的参数。如果头包含了 Set-Cookie 字段,则不会缓存此类响应。

如果头包含有特殊值 * Vary 字段,则不会缓存此类响应(1.7.7)。如果头包含有另一个值的 Vary 字段,这样的响应则将考虑缓存相应的请求头字段(1.7.7)。

为不同的响应状态码设置缓存时间。如果是proxy_cache_valid5s,则200301302响应都将被缓存。

指令proxy_cache_valid不是唯一设置缓存时间的,还可以通过如下方式(优先级从上到下)。

1.以秒为单位的“X-Accel-Expires”响应头来设置响应缓存时间。

2.如果没有“X-Accel-Expires”,则可以根据“Cache-Control”、“Expires”来设置响应缓存时间。

3.否则,使用proxy_cache_valid设置缓存时间。

如果响应头包含Cache-Controlprivate/no-cache/no-storeSet-Cookie或者只有一个Vary响应头且其值为*,则响应内容将不会被缓存。可以使用proxy_ignore_headers来忽略这些响应头。

如果NGINX无法通过上述途径获得有效期,NGINX将不会为响应生成缓存文件。

Syntax:proxy_ignore_headers field ...;

Default:—

Context:http, server, location

忽略上游服务器返回的特定的响应头部。这些头部包括:“X-Accel-Redirect”, “X-Accel-Expires”, “X-Accel-Limit-Rate” (1.1.6), “X-Accel-Buffering” (1.1.6), “X-Accel-Charset” (1.1.6), “Expires”, “Cache-Control”, “Set-Cookie” (0.8.44), and “Vary” (1.7.7)

如果不忽略处理这些头部,他们产生的效果如下:

“X-Accel-Expires”, “Expires”, “Cache-Control”, “Set-Cookie”, and “Vary” 影响缓存有效期。

“X-Accel-Redirect” 内部重定向到某个特定URI

“X-Accel-Limit-Rate” 设置到客户端的rate limit数值。

“X-Accel-Buffering” 启用或者禁止proxy_buffering

“X-Accel-Charset” 设置发向客户端的字符集。

Syntax:proxy_intercept_errorson | off;

Default:proxy_intercept_errors off;

Context:http, server, location

对于上游返回的大于300的错误返回码是否需要重新处理再返回客户端。

数据结构

继续引用上篇文章中的数据结构图,这样可以随时查看相关数据结构之间的关系。

原理

在生成缓存文件时,NGINX会根据客户端发来的请求以及指令proxy_cache_key中的配置参数使用md5生成一个32位的16进制数值。

比如配置如下的服务器:

proxy_cache_path/data/cache levels=2:2 keys_zone=jikuicdn:10m inactive=6000m;

server {

    listen 80;

    location/ {

        proxy_cache_key $scheme$proxy_host$request_uri;

        proxy_cache jikuicdn;

        add_header X-Cache-Status $upstream_cache_status;

        proxy_pass http://10.145.73.28/;

    }

}

在客户端执行请求curl http://10.145.70.103/index.html。 则NGINX对此请求生成的key值是"http10.145.73.28/index.html"

计算此key值的md5 hash可以得到:

[jikui@nginx-dev ~]$ echo -n "http10.145.73.28/index.html" | md5sum

85c8a32fc36adfde2824ec3fc06d9304-

对于此请求后端服务器返回的响应,NGINX会生成一个key值为85c8a32fc36adfde2824ec3fc06d9304ngx_http_file_cache_node_t的结构并且插入到红黑树节点中。同时还会并且根据proxy_cache_path的配置生成如下名为85c8a32fc36adfde2824ec3fc06d9304的磁盘文件存放到配置的路径下。

[jikui@nginx-dev ~]$ ls -al /data/cache/04/93/

total 8

drwx------ 2 jikui users  46 Jan 16 03:02 .

drwx------ 3 jikui users   16 Jan 16 03:02 ..

-rw------- 1 jikui users 4729 Jan 16 03:02 85c8a32fc36adfde2824ec3fc06d9304

存放在磁盘上的缓存文件内容格式如下所示:

[ngx_http_file_cache_header_t]["\nKEY: "][orig_key]["\n"][header][body]中的[orig_key]["\n"]

第一部分是数据结构ngx_http_file_cache_header_t的内容,第二部分是生成文件名所需要的key值,一般是指令proxy_cache_key定义的参数。第三部分就是发送给客户端的文件内容,包括headerbody两部分。

NGINX收到一个请求以后,计算请求对应的keymd5sum值然后使用该hash值作为key去搜索是否存在缓存文件,如果存在并且有效则尝试使用此文件响应客户请求。

缓存生成

在接收到上游响应并准备向下游发送之前,upstream 模块会判断是否需要对响应进行缓存并设置相关信息。这个过程主要在函数 ngx_http_upstream_send_response 中完成,具体流程为:

1.     调用函数ngx_http_test_predicates判断是否满足生成缓存文件的条件。函数ngx_http_test_predicates会根据proxy_no_cache指令的配置来判断是否需要生成缓存文件。

2.     如果函数ngx_http_test_predicates返回NGX_ERROR,则通过ngx_http_upstream_finalize_request(r, u, NGX_ERROR)直接返回错误。如果返回NGX_DECLINE则表示不需要生成缓存文件。

3.     如果返回NGX_OK则表示需要生成缓存文件,同时把结构ngx_http_upstream_t中的cacheable变量设置为1

4.     获得缓存文件的有效期。缓存文件的有效期首先是通过上游服务器返回的响应头部中的X-Accel-ExpiresCache-Control,或者Expires头部信息来获得。如果返回没有上述头部信息,则通过函数ngx_http_file_cache_valid获取通过指令proxy_cache_valid设置的有效期。如果无法获得要生成缓存文件的有效期,则NGINX不会生成缓存文件。

5.     如果需要缓存通过如下步骤生成缓存文件的内存meta信息和磁盘文件:

a.     通过函数ngx_http_file_cache_exists判断系统内存中是否已经存在着缓存文件的红黑树节点,如果存在则重新刷新缓存文件的有效期。如果没有,则生成一个新的ngx_http_file_cache_node_t红黑树节点并且插入到内存红黑树中。至此,缓存文件的meta信息就已经生成完毕。

b.    通过函数ngx_http_file_cache_create通过对请求的keys进行md5 hash生成缓存文件的文件名。

c.     通过函数ngx_http_file_cache_set_header初始化缓存文件的ngx_http_file_cache_header_t头部信息结构已经生成文件名所用的key值。这个结构信息也同时会被写入磁盘缓存文件的头部。[ngx_http_file_cache_header_t]["\nKEY: "][orig_key]["\n"][header][body]

6.     在有buffering的时候,NGINX使用ngx_event_pipe进行数据转发。函数ngx_event_pipe调用ngx_event_pipe_read_upstream读取upstream发送的数据并且通过函数ngx_event_pipe_write_chain_to_temp_file写入临时文件中。

7.     等上游服务器请求接收完毕通过函数ngx_http_file_cache_update把临时文件重命名为正式的缓存文件。

缓存使用

再来分析一下在正常请求处理过程中,一个请求是怎样使用缓存 数据的 (同时,在分析代码过程中还需要注意的是, NGINX 允许 Cache Loader 进程在加载缓存文件信息的同时响应这些对缓存的请求,这个特性用于提高 NGINX本身的可用性)

所有请求缓存使用的尝试,都是通过 ngx_http_upstream_cache 函数开始的。 这个函数的主要流程是:

1.     如果还未给当前请求分配缓存相关结构体 (ngx_http_cache_t) ,则调用函数ngx_http_file_cache_new创建此类型字段 (r->cache) 并初始化。

2.     通过函数ngx_http_proxy_create_keyproxy_cache_key配置的缓存key进行取值。

3.     通过函数ngx_http_file_cache_create_key身材md5sum(key)crc32(key)并计算header_start值。

4.     调用函数ngx_http_test_predicates根据指令proxy_cache_bypass的配置信息,来判断对于本次请求是不是要绕过缓存文件直接通过后端服务器进行获取。

5.     调用函数ngx_http_file_cache_open查找是否有对应的有效缓存数据。函数ngx_http_file_cache_open我们下面接着分析。

6.     如果缓存命中,调用ngx_http_upstram_cache_send 函数发送缓存数据给请求者。如果缓存未命中,继续正常 upstream 请求处理流程。

函数ngx_http_file_cache_open 函数负责缓存文件定位、缓存文件打开和校验等操作,其返回值及对应含义,以及其调用者 ngx_http_upstream_cache 对应的行为总结如下:

1.     NGX_OK

         - 缓存正常命中

        - 设置 `cache_status` `NGX_HTTP_CACHE_HIT`,然后向客户端发送缓存内容

2.     NGX_HTTP_CACHE_STALE

        - 缓存内容过期,当前请求需要向后端请求新的响应数据。

        - 设置 `cache_status` `NGX_HTTP_CACHE_EXPIRED`,并返回 `NGX_DECLINED`

     以继续请求处理 (`r->cached = 0; c->valid_sec = 0`)

3.     NGX_HTTP_CACHE_UPDATING

        - 缓存内容过期,同时己有同样使用该缓存节点的其它请求正在请求新的响应数据。

        - 如果 proxy_cache_use_stale 启用了 "updating",设置 `cache_status`

         `NGX_HTTP_CACHE_UPDATING`,然后向客户端发送过期缓存内容。否则,将返回

         值重设为 `NGX_HTTP_CACHE_STALE`

4.     NGX_HTTP_CACHE_SCARCE

        - 因缓存节点被查询次数还未达 `min_uses`,对此请求禁用缓存机制

        - 继续请求处理,但是不再缓存其响应数据 (`u->cacheable = 0`)

5.     NGX_DECLINED

         - 缓存内容因为不存在 (`c->exists == 0`)、缓存内容未通过校验、或者当前请

            求正在更新缓存等原因,暂时无法使用缓存。

         - 继续请求处理,并尝试对其响应数据进行缓存。

6.     NGX_AGAIN

        - 缓存内容过期,并且当前缓存节点正在被其它请求更新,或者 还未能从缓存文

           件中读到足够的数据 (aio 模块下)

         - 返回 `NGX_BUSY`NGINX 会再次尝试读取缓存。

7.     NGX_ERROR

         - 内存相关、文件系统等系统错误。

        - 返回 `NGX_ERROR`NGINX 会调用 `ngx_http_finalize_request` 终止此请求。

8.     NGX_HTTP_SPECIAL_RESPONSE

        - 打开 `proxy_intercept_errors` 配置情况下,直接返回缓存的错误码。

        - 设置 `cache_status` `NGX_HTTP_CACHE_HIT` 并返回错误码。

函数 ngx_http_file_cache_open 的主要逻辑如下:

1.     第一次根据请求信息生成的 key 查找对应缓存节点时,先注册一下请求内存池级别的清理函数:

2.     调用 ngx_http_file_cache_exists 函数,使用 ngx_http_file_cache_lookup 函 数以 c->key 为查找条件从缓存中查找缓存节点:

a.     如果找到了对应 c->key 的缓存节点:

i)      如果该请求第一次使用此缓存节点,则增加相关引用和使用次数,继续下面条件判断;

ii)     如果 proxy_cache_valid 配置指令对此节点过期时间做了特殊设定,检查节点是否过期。

       过期,重置节点,并返回 NGX_DECLINED; 如果未过期,返 回 NGX_OK

iii)     如果缓存文件存在或者缓存节点被使用次数超过 proxy_cache_min_uses 配置值,置 c->error = fcn->error,并返回 NGX_OK

iv)     条件 2, 3 都不满足时,此次查找失败,返回 NGX_AGAIN

b.    如果未找到对应 c->key 的缓存节点,创建并创始化新的缓存节点,同时返回 NGX_DECLINED

3.     调用 ngx_http_file_cache_name 函数生成缓存文件完整文件名。

4.     调用 ngx_open_cached_file 函数尝试打开并获取文件缓存信息。

5.     创建用于存储 缓存文件头的临时缓冲区 c->buf

6.     调用 ngx_http_file_cache_read 函数读取缓存文件头并进行有效性验证。

7.     文件内容通过ngx_http_upstream_cache_send调用ngx_http_cache_send来完成发送。

缓存使用和生成涉及的基本流程大致分析完毕了,其中涉及 cache_lock 等诸多细节因为篇幅原因,暂时不做分析。

总结

缓存是NGINX最重要的功能之一。通过两篇文章,我们大体分析了NGINX缓存工作的原理。就缓存的实现来说,内容很多,细节也很庞杂。所以在进行源码分析时很多细节都没有顾及到。很多细节留给我们自己阅读代码时去体会。还有NGINX Plus中提供了Cache  Purge功能,有一些开源版本的模块也可以实现purge功能。


已修改于2023-03-09 02:06
本作品系原创
创作不易,留下一份鼓励
皮皮鲁

暂无个人介绍

关注



写下您的评论
发表评论
全部评论(0)

按点赞数排序

按时间排序

关于作者
皮皮鲁
这家伙很懒还未留下介绍~
85
文章
2
问答
41
粉丝
相关文章
1.查看已有模块/usr/local/nginx/sbin/nginx-V 1此处我是安装了配置SSL想在此加上FastDFS模块将红色的地方复制出来记到一个小本本上./configure--prefix=/usr/local/nginx--with-http_stub_status_module--with-http_ssl_module--add-module=/usr/local/fastdfs-nginx-module/src/ 12.重新编译Nginx在此位置重新执行上面的:./configure--prefix=/usr/local/nginx--with-http_stub_status_module--with-http_ssl_module--add-module=/usr/local/fastdfs-nginx-module/src/千万不要makeinstall,不然就真的覆盖了make//千万不要makeinstall,不然就真的覆盖了 1先备份一波,备胎还是需要的/usr/local/nginx/sbin/nginx
点赞 4
浏览 1.4k
nginx_substitutions_filter *Note:thismoduleisnotdistributedwiththeNginxsource. Installationinstructionscanbefoundbelow.* Description nginx_substitutions_filterisafiltermodulewhichcandobothregular expressionandfixedstringsubstitutionsonresponsebodies.This moduleisquitedifferentfromtheNginx'snativeSubstitutionModule. Itscanstheoutputchainsbufferandmatchesstringlinebyline,just likeApache'smod_substitute
点赞 0
浏览 1.2k
Description: Anginxmoduletoaddastickycookietobealwaysforwardedthethesame upstreamserver. Whendealingwithseveralbackendservers,it'ssometimesusefulthatone client(browser)isalwaysservedbythesamebackendserver (forsessionpersistanceforexample). UsingapersistancebyIP(withtheip_hashupstreammodule)ismaybenot agoodideabecausetherecouldbesituationswherealotofdifferent browsersarecomingwiththesameIPaddress(behindproxie
点赞 1
浏览 1k