概述
缓存是计算机领域的一种非常重要设计。主要用来提升响应速度。比如计算机系统中的存储体系就是这一经典缓存的实现。它是由寄存器,缓存,内存,磁盘,网络组成的一个层级体系,用来存储各种信息。类比日常生活中,我们对于知识的存储系统也是一个层级的缓存体系。它是由我们的大脑,笔记本,身边朋友,书籍,网络组成的。这些层级系统有一个共同的特点就是层级越高它的容量越小,速度越快但是同时价格也越贵。
在我们使用浏览器获取信息时,也有一个缓存体系在发挥作用。那就是客户端浏览器缓存,中间各级代理设备缓存,服务器缓存,服务器源文件。
这种网络的缓存对于提升响应速度有非常好的作用。尤其是在分布式系统中,提到了非常大的作用。具体说来,网络缓存的主要作用有:
- 缓存减少了冗余的数据传输,节省了网络费用。
- 缓存减缓了网络瓶颈的问题,不需要更高的带宽就能够更快地加载页面。
- 缓存减少了对原始服务器的请求,服务器可以更快地响应,避免过载。
- 缓存减缓了距离时延,因为从较远的地方加载页面会更慢一些。
NGINX作为代理设备通过自身的缓存功能来提高响应速度。下面我们试着去分析NGINX缓存功能的工作原理和源码实现原理。
原理
如下图所示,NGINX缓存功能就是通过把上游服务器的文件存放到本地磁盘上,然后在一定条件下直接使用它们来应答下游请求。 这样省去了和上游服务器的交互的时间,从而提高了效率,减轻了网络和上游服务器压力。
从实现角度来讲,如下图所示,NGINX从上游服务器获取到要缓存的文件后,需要在内存中维护一份它的元数据(meta data),并且在磁盘上保存文件完整数据。同时NGINX需要对两者进行有效的管理,比如维护两者的一致性,在一定条件下删除某些文件等。
NGINX的缓存功能都是围绕上述数据结构进行的。主要包括以下四个功能:
- 管理
维护上图数据的一致性,定期删除过期缓存文件或者强制删除某些缓存文件来释放磁盘空间。
- 加载
在NGINX启动时,如果对应目录中存在缓存文件,则需要生成对应内存中的文件元数据。
- 生成
从上游获取文件时,如果需要缓存则创建内存中的元数据以及对应磁盘中的文件。
- 使用
新的请求到来时,如果有对应的缓存文件可用,则直接使用磁盘中的文件返回。
配置了缓存功能后,NGINX就会启动Cache Manager进程和Cache Loader进程用来分别完成功能1和功能2。Cache Manager是一个常驻进程,它周期性地运行来淘汰过期缓存或者强制删除某些缓存文件释放磁盘空间。在两次缓存管理器启动的间隔,缓存的数据量可能短暂超过配置的大小。
与Cache Manager不同,Cache Loader进程只在启动时运行一次,完成任务后就退出。NGINX 启动1分钟之后,Cache Loader进程生成现有的缓存文件的元数据并且加载到共享内存区域中。
功能3和功能4是NGINX的worker进程在处理HTTP请求过程中完成的。
NGINX缓存实现涉及的总体内容比较多,我们将分成两部分进行分析。本篇文章,我们侧重分析功能1和功能2,也就是NGINX是如何管理和维护缓存数据的,以及在启动阶段,磁盘中的文件是如何生成对应的内存中的元数据的。
配置
如下所示,只需要proxy_cache_path 和 proxy_cache 两条指令就可以开启内容缓存,前者用来设置缓存的路径和配置,后者用来启用缓存。
http {
...
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;
proxy_cache_valid 30m;
server {
proxy_cache mycache;
location / {
proxy_pass http://localhost:8000;
}
}
}
指令 proxy_cache_path:
Syntax:proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [min_free=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=num