nginx的缓存

来源:互联网 发布:ida软件 编辑:程序博客网 时间:2024/06/07 17:11
nginx的缓存:proxy_store存储方式按照url中的文件路径,存储在本地,nginx在指定的存储目录下依次建立各个目录和文件,性能不好(文件名长度不一致,文件的打开和查找都很慢)。proxy_cache(自定义方式,不会因url长度而产生复杂性增加和性能的降低)。

nginx根据配置生成缓存对象的key,用md5。大多数文件系统下,对单个目录下的文件数量有限制,采用多级目录,levels指令用于指定目录层数(冒号分隔)和每个目录名字的字符个数。levels=1:2代表使用两级目录,第一级目录名是一个字符,第二级目录用两个字符。nginx最大支持三级目录。该结构是一个通用组件,所以需要一些特殊的标记来处理涉及存储的相关功能,cacheable。

nginx的边收边发,使用的结构是ngx_event_pipe_t,是沟通后端和客户端的媒介。

nginx在取后端数据时,它的行为受proxy_buffering控制,作用是为后端的服务器启用应答缓冲。如果启用缓冲,nginx假设被代理服务器能够非常快的传递应答,并将其放入缓冲区,可以使用proxy_buffer_size和proxy_buffers设置相关参数。如果响应无法全部放入内存,则将其写入硬盘。如果禁用缓冲,从后端传来的应答将立即被传送到客户端。
nginx在ngx_http_upstream_init_request函数中完成缓存对象的创建,这个函数在跟后端建立连接之前调用。创建过程函数为ngx_http_upstream_cache。
对象创建完成后,缓存对象管理结构由ngx_http_file_cache_exists函数处理。

假设存储目录为/cache,levels=1:2。则最后的文件缓存名为:/cache/0/8d/8ef9229f02c5672c747dc7a324d658d0


作为缓存服务器,响应头必须和被代理的后端服务器一致,所以是将http响应头和内容都缓存在文件中。

在nginx中每个文件都在内存中都有相应的控制结构,称为一个node。这个结构是在共享内存中申请和管理的。因为nginx是多进程模型。这个node是结构体ngx_http_file_cache_node_t。当一个node首次创建之后,需要放入到系统的缓存管理体系中,nginx用到的是红黑树,所有的node都被插入到树里面,然后还要放到lru队列中,作用就是在存储空间不够的时候,通过lru来删掉一些对象,同时也会删除内存中的控制结构
nginx如何将收到的后端数据写到本地磁盘文件里去: 核心思想是这样的,nginx首先会将数据写到一个临时文件中去,然后内容收完之后,再将这个临时文件rename到实际的目标文件。关于linux文件系统中元数据的加锁机制和组织方式:http://www.ibm.com/developerworks/cn/linux/l-cn-fsmeta/
ngx_http_file_cache_node_t结构中有两个成员需要注意,一个是count,表示当前正在使用这个node的请求数,另一个成员uses记录了到目前为止,这个node被访问的次数,这个值是一直累加的。

一个缓存服务器异常停机或者要进行维护关机了,当机器再次启动缓存服务的时候,重建之前的缓存,缓存文件还在磁盘上,缺失的只是内存中的控制信息。使用cache loader process进程完成。 如果文件比较多,重建过程可能会很慢,为此nginx使用了三个个变量来控制速度,loader_thresholdloader_filesloader_sleep

 缓存过期:manager进程的一个重要的作用就是监控过期,做lru等工作。我们把这个manager进程发现过期的情景称为主动发现,worker进程在处理请求时也会发现某个对象过期,这个称为被动发现。它的基础就在于管理缓存对象的控制结构及其信息是由master进程通过共享内存创建并初始化的,这样manager和worker在被fork之后,这些信息就是共享的了。manager进程在运作时,从lru队列的尾部开始,检查是否有文件过期。有过期的就删掉。至于为什么从lru队列的尾部检查,是因为在worker处理对象的时候,每次hit一个文件(一个正常的文件必然位于lru队列中),该文件就从队列中删掉,然后插到队列头部去,所以越靠近尾部的对象,越是较长时间没有被访问到的,LRU的思想也在于此。 

在一个文件的开头部分,存放了一些有关文件的控制头信息,前面已经提过了。这个头信息中有相关的变量标记这个对象保鲜时间,所以只需要读出这个变量跟当前时间比较一下就可以了。当缓存过期时,请求重新发回后端服务器时,updating的变量此时会被置1。此时这个文件相关的管理结构还未被从系统里释放,所以后续的请求还是会hit,不过后面的处理还是会发现过期,这样只要一个请求在更新完成之前,对于该文件的请求,都会去后端取文件(即透传)。
proxy_cache_lock处理并发取源。当文件过期时,会产生大量的并发回源量,通过proxy_cache_use_stale来控制在文件过期过程中的回源请求量,当一个请求再更新文件时,其他请求暂时使用过期文件。

proxy_cache_lock开启时,ngx_http_cache_t结构中的lock成员被置为1.ngx_http_cache_t结构用于沟通请求与其对应缓存对象。当一个对象未缓存完整时,一个名为updating的成员会置1,同时exists成员置0。在开启fetch merged的时候,nginx会让后续的请求等待一段时间(默认是5秒,通过proxy_cache_lock_timeout配置)。在这段时间内,nginx每500ms去检查缓存是否正常结束(updating是否被置0),如果结束了,那么就会在后面的处理流程中发现已经缓存好的文件,即可hit了。如果时间挺长,过了等待的最长时间,那么针对该缓存文件的fetch merged机制就会cancel,这样后续的请求就会跟普通情况下一样,继续去后端fetch文件了。当然这里的cancel处理不会影响其他文件的fetch merged。这个功能对于大文件很鸡肋。

改善:http://blog.csdn.net/brainkick/article/details/8583335

文件过期: inactive的时间表示一个文件在指定时间内没有被访问过,就从存储系统中移除,不管你proxy_cache_valid里设置的时间是多少。而proxy_cache_valid在保证inactive时间内被访问过的前提下,最长的可用时间。proxy_cache_valid定义的其实是一个绝对过期时间(第一次缓存的时间+配置的缓存时间),到了这个点,对象就被认为是过期,然后去后端重取数据,尽管它被访问的很频繁(即所谓的inactive时间内)。expires呢,它不在这个过期控制体系内,它用在发给客户端的响应中,添加"Expires"头。
0 0
原创粉丝点击