Nginx配置缓存
Be a king of caching
今天我将向您展示如何使互联网更快更稳定。如何轻松适应Nginx的缓存,以提升您的应用程序。
缓存概念
在我们开始之前,我需要做一个先验假设。即内容是准实时的。这意味着我们的数据或您希望我们的HTTP响应,不要经常更改。请注意,“不经常”这个短语并不是一个严格的定义。它可以是1秒,1小时,1周等。
好吧,考虑到这一点,让我们从最初的情况开始,不涉及缓存,看起来像这样。
用户向应用程序发出请求并获得响应。
在此方案中添加缓存是提高性能,容量和可用性的简单方法。它的工作原理是将服务器或应用程序的响应保存到本地存储或内存。
让我们考虑一下这种简单的情况。客户端像上一个示例一样向应用程序发出请求,但这次他通过缓存。
应用程序响应和缓存会将此响应转发给客户端,但它也会将其保存在本地。
下次用户执行相同的请求时,缓存会检查它是否已有此信息。
如果是这种情况,它会通过提供此缓存内容立即响应用户。
请注意,第二个请求根本不涉及申请。
缓存增加了系统的复杂性,但它带来了很多好处:
- 它提高了网站性能 - 请求不必经历整个渲染过程
- 它通过减少原始服务器的负载来增加容量
- 它还提供更高的可用性 - 通过在原始服务器关闭时提供陈旧内容
在我们开始使用Nginx之前,我想提一下缓存内容的替代方法。Squid Cache和Varnish Cache是我最喜欢的例子。我在职业生涯中看到的标准用例如下:
您只需将缓存放在HTTP服务器前面。在应用程序服务器上或在专用机器上:
这显然增加了系统的复杂性,但它可能更适合您的情况。阅读,比较功能并做出决定。
在这篇文章中,我们将只关注Nginx。
使用Nginx进行缓存
Nginx是一个HTTP服务器,它非常适合提供静态文件和代理请求。由于其异步性质,它具有轻量级资源利用率。
在缓存方面,Nginx集成了:
- HTTP服务器
- FastCGI的
- uwsgi
- SCGI
现在我们知道缓存如何工作以及Nginx是什么。我们来看看Nginx的缓存实现。
一个例子应该说清楚。首先,客户端提出请求。
示例HTTP请求如下图所示:
基于它的一些细节,Nginx生成一个哈希键。
现在Nginx检查内存中是否已存在此哈希键。如果没有,请求将转到应用程序。
应用程序应答并将其响应保存到文件系统。
此外,先前生成的哈希密钥将保存到内存中。为了便于理解,我将散列键值与保存文件的位置一起可视化。但请记住,Nginx只在内存中存储哈希键。
最后,用户得到了回复。
当我们的客户端第二次请求相同的URL时,Nginx再次生成散列密钥并检查它是否存在于内存中。这次它就在那里,所以Nginx从与散列键相关联的文件系统提供缓存文件。
请注意,第二个请求根本不涉及申请。
对于第二个请求,客户端不会等待应用程序首先从数据库中获取数据,然后呈现页面。相反,Nginx提供具有缓存版本响应的静态文件。
此外,这些文件很可能缓存在内存中。这次不是由Nginx(尽管它给操作系统提供了一些提示)而是由操作系统提供的。使用尽可能高效的资源是Linux的属性。这使得从文件系统中读取文件非常快。
配置 - 可用指令
现在我们已经了解了Nginx缓存如何工作的技术背景,让我们看看我们如何配置它。
首先在http
关卡中我们定义数据的存储位置。我们在文件系统和内存区域及其大小上指定路径。该内存区储存唯一元哈希键-对缓存的项目的信息。
注意
每个项目都占用大约
0.125 kB
内存,因此我们可以存储大量内存。在1MB
例如Nginx的可以存储大约8000缓存键
。
基本
基本缓存定义如下所示:
proxy_cache_path /data/nginx/cache keys_zone=zone_name_one:10m;
要启用它,我们只需使用该proxy_cache指令。
proxy_cache zone_name_one;
也可以通过添加max_size
参数来限制用于存储缓存内容的文件系统的大小。
proxy_cache_path /data/nginx/cache keys_zone=one:10m max_size=200m;
然后,我们还可以选择何时在特定时间内不使用文件时(从缓存中删除文件)。
proxy_cache_path /data/nginx/cache keys_zone=one:10m inactive=60m;
还有一个很好的小参数,让我们定义缓存的层次结构级别。
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m;
下图说明了层次结构级别配置:
现在让我们看看你是否正确理解它。准备好测验?根据下图,level参数应该是什么?
答案是2:4
,如果我们看一下下面的图像就更清楚了:
什么/何时缓存?
默认情况下,Nginx
仅缓存GET
和HEAD
请求。您可以使用proxy_cache_methods
指令更改此设置:
proxy_cache_methods GET HEAD POST;
您还可以指示Nginx仅在请求响应至少5次后才缓存响应。
proxy_cache_min_uses 5;
这在您拥有大量内容的情况下非常有用,但您只想缓存那些非常受欢迎的请求。
Nginx也可以为我们节省上行带宽和磁盘写入。通过尊重缓存标头和304, not modified
响应,如果启用以下指令,Nginx将不会再次下载内容:
proxy_cache_revalidate on;
如何缓存?
使用Nginx,我们不限于通过相同的规则缓存所有内容。相反,我们可以告诉Nginx应该使用哪些信息来生成散列密钥。我们可以做到这一点的http
,server
或者location
水平。以下是两个例子:
proxy_cache_key "$host$request_uri$cookie_user";
proxy_cache_key "$scheme$proxy_host$uri$is_args$args";
我们也可以告诉Nginx,在哪些情况下请求不应该存储在缓存中
。
proxy_no_cache $http_pragma $http_authorization $cookie_nocache $arg_nocache;
缓存多长时间?
有一个简单的指令告诉Nginx缓存某种类型的响应多长时间:
proxy_cache_valid any 1m;
proxy_cache_valid 200 302 10m;
但主要是源服务器的头部定义了内容的可缓存性:
- 过期
- 缓存控制
- X-Accel-Expires - Nginx特殊标题。
覆盖其他标头。当您需要向客户端提供不同的标头时使用。
上述选项的优先级如下图所示,最重要的是:
其他
以下选项为可用性因素增加了很多。当应用程序响应超时或返回50x状态代码时,它允许Nginx提供过时(旧的,过期的)内容:
proxy_cache_use_stale error timeout;
另一个很酷的功能是只允许第一个请求通过应用程序。这可以通过以下方式启用:
proxy_cache_lock on;
您已经知道,原始返回的内容将流式传输到磁盘。默认情况下,proxy_cache_path
指令中定义的位置。您还可以将这些文件存储在临时目录中,然后再将其移动到缓存路径。如果您需要此行为,请使用此:
proxy_temp_path /tmp/custom_cache/;
该指令适用于多个缓存。但请记住,它的效率始终低于临时路径与缓存路径相同的效率
调试Nginx的缓存
我认为以正确的方式调试任何软件比实际了解软件本身更重要。良好的调试过程可确保更好地理解,最重要的是,可以非常快速地解决难题。
在本章中,我将向您展示轻松调试Nginx缓存的一些技巧。
第一个技巧是绕过缓存。
proxy_cache_bypass $arg_nocache $cookie_nocache $arg_comment;
上面的指令允许您指定何时省略缓存
。这意味着带有nocache=true
查询参数的每个请求都会转到原点。甚至可能是Nginx也会缓存结果。
另一个技巧是添加包含缓存状态信息的标头。您只需添加标题即可:
add_header X-Cache-Status $upstream_cache_status;
或者以下面介绍的更复杂的方式,它只允许本地请求查看标题:
map $remote_addr $cache_status {
127.0.0.1 $upstream_cache_status;
default "";
}
...
add_header X-Cache-Status $cache_status;
通过调试X-Cache-Status
标题,您将欣赏下表:
- | - |
---|---|
MISS | Object was not found in the cache. Response was served from the origin. Response may have been saved to cache. |
BYPASS | Got response from upstream. Response may have been saved to cache. |
EXPIRED | Cached object has expired. Response was served from the upstream. |
STALE | Object served from cache because of issues with origin server response |
UPDATING | Serve stale content from cache because proxy_cache_lock has timed out and proxy_use_stale takes controll |
REVALIDATED | proxy_cache_revalidate verified that the current cached content was still valid |
HIT | The object was found in the cache and it is served from there |
在接下来的两章中,我们将了解维护缓存文件涉及哪些进程。在我们开始讨论很酷的例子后,这些章节非常简短。所以和我在一起!
缓存加载器
Nginx缓存加载器是一个负责从磁盘加载缓存的进程。
它只运行一次(启动时)并将元数据加载到内存区域。它在迭代中运行,直到加载所有键。
我们可以使用以下选项调整它的行为(以正确的方式利用CPU):
- loader_threshold - 一个迭代时间有多长
- loader_files - 不要加载更多的物品
- loader_sleeps - 迭代之间的暂停时间
下面给出一个例子:
proxy_cache_path /data/nginx/cache keys_zone=one:10m [loader_files=number] [loader_sleep=time] [loader_threshold=time];
下面的漫画显示缓存加载器仅在启动时使用,并且它在由所描述的参数定义的迭代中工作。
缓存管理器
Nginx缓存管理器是一个随时间清除缓存的过程。
如果文件大小超过,它会定期检查文件存储并删除最近最少使用的数据max_size。它还会删除未独立于缓存设置使用的文件。
观看下面的漫画,其中说明了缓存管理器职责
两个实例
例子一
upstream backend {
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
}
#代理缓存空间
#levels:缓存文件按照两层目录进行分级保存
#keys_zone:定义这个空间的名字,10m为这个空间的大小(一般1m可以存放8000个key)
#max_size:这个缓存空间的最大空间,满了会触发淘汰规则进行处理
#inactive:不活跃时间 表示在60分钟内,如果该缓存文件没被访问,会把它清理掉
#use_temp_path:临时文件,建议关闭。
proxy_cache_path /opt/site/cache levels=1:2 keys_zone=sam_cache:10m max_size=10g inactive=60m use_temp_path=off;
server {
listen 80;
server_name localhost www.sam.com;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
#匹配uri,如果uri为 /login 或 /register 或 /password/reset,添加变量$cookie_nocache 值为1
if ($request_uri ~ ^/(login|register|password\/reset)){
set $cookie_nocache 1;
}
location / {
proxy_pass http://backend;
proxy_cache sam_cache; #使用前面定义的proxy_cache_path
proxy_cache_valid 200 304 12h; #设置200和304过期时间为12h
proxy_cache_valid any 10m; #其他过期时间为10分钟
proxy_cache_key $host$uri$is_args$args; #修改缓存纬度,缓存的key
add_header Nginx-Cache "$upstream_cache_status";
#配置不缓存的,如果上面条件判断中有新增变量$cookie_nocache,那么对应请求不进行缓存
proxy_no_cache $cookie_nocache;
#当命中的服务器出现错误、超时、请求头不完整、500、502、503时,会跳过这一台服务器去访问下一台服务器。
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
###### 以下是代理常规配置 ######
proxy_redirect default; #一般配置默认即可
#添加头信息
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
#配置超时
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
#配置缓冲区,
proxy_buffer_size 32k;
proxy_buffering on;
proxy_buffers 4 128k;
proxy_busy_buffers_size 256k;
proxy_max_temp_file_size 256k;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
例子二
# proxy_cache_path 缓存的基本配置,需要放在 server 的外面,下面是配置项
# 缓存文件路径:/data/nginx/cache(自定义)
# keys_zone 设置缓存名字和共享内存大小 one-cache:50m
# levels 设置缓存文件目录层次;levels=1:2 表示两级目录
# inactive 删除指定时间内未被访问的缓存文件
# max_size 缓存硬盘空间最多为 200m,如果缓存空间满,默认覆盖掉缓存时间最长的资源。
# 下面两项是 nginx 启动时加载缓存的参数
# loader_threshold 加载器每次迭代过程最多执行300毫秒
# loader_files 加载器每次迭代过程中最多加载200个文件
proxy_cache_path /data/nginx/cache keys_zone=one-cache:50m levels=1:2
inactive=7d loader_threshold=300 loader_files=200 max_size=200m;
#百度语音识别接口跨域代理
server {
listen 80;
server_name vop-baidu.proxy.abc.com;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With,content-type;
add_header Access-Control-Allow-Methods GET,POST; #,OPTIONS;
add_header Access-Control-Max-Age 99999999;
location / {
proxy_pass http://vop.baidu.com;
}
#百度语音 token
location /token {
proxy_cache one-cache; # 使用名称为one-cache的缓存(必须)
proxy_cache_methods GET HEAD POST; #配置需要缓存的方法 默认GET|HEAD
proxy_cache_valid 200 302 10d; # 对200和302状态的请求缓存10天,any 表示所有状态
proxy_cache_key $uri; # 定义缓存key 默认是请求URL
#****很重要*** 此项适用于配置要忽略的proxy_pass目标服务器的响应 header 项,
#当目标服务器设置了 Cache-Control或Set-Cookie header等项时 则响应
#不会被缓存或影响缓存策略,所以这里选择忽略
proxy_ignore_headers Cache-Control Set-Cookie;
proxy_pass https://openapi.baidu.com/oauth/2.0/token?xxxxxxx;
}
}