文章原创于公众号:程序猿周先森。本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号。

上篇文章介绍了Nginx一个较为重要的知识点:Nginx实现接口限流。本篇文章将介绍Nginx另一个重要知识点:Nginx缓存原理。其实说到缓存技术大家应该都不会很陌生,缓存技术的基本思想其实是对用户已经访问过的内容在Nginx建立副本,如果在一段时间内(缓存尚未过期)再次访问该数据,则不需要重新发起请求获取数据,可以直接从缓存中读取到该数据,好处在于减少了Nginx与后端服务之间的网络交互,减轻了网络的压力,而且在减少数据传输的延迟时同时可以提升用户访问速度。而且如果碰上后端服务出现异常时,还可以通过缓存进行相应用户请求,提高了后端服务的稳定性。

什么是Nginx缓存?

Nginx基于Proxy Store实现,使用Nginx的http_proxy模块可以实现类似于squid的缓存功能。当启用缓存时,Nginx会将相应数据保存在磁盘缓存中,只要缓存数据尚未过期,就会使用缓存数据来响应客户端的请求。

如何启用缓存?

Nginx启用缓存需要在最顶层的http节点下配置proxy_cache_path命令。我们先看看proxy_cache_path命令的语法结构:

  • proxy_cache_path /data/cache keys_zone=niyueling:10m;

可以看到proxy_cache_path命令一共包含两个参数,第一个参数指定缓存保存的本地路径,第二个参数定义缓存数据的共享内存区域的名称和内存区大小。Nginx启动后,缓存加载程序只进行加载一次,加载时会将缓存的元数据加载到共享内存区域,但是如果一次加载整个缓存全部内容可能会使Nginx刚启动的前几分钟性能消耗严重,大幅度降低Nginx的性能。所以可以在proxy_cache_path命令中配置缓存迭代加载。缓存迭代加载一共可以设置三个参数:

  • loader_threshold - 迭代的持续时间,以毫秒为单位(默认为200)
  • loader_files - 在一次迭代期间加载的最大项目数(默认为100)
  • loader_sleeps - 迭代之间的延迟(以毫秒为单位)(默认为50)

我们可以看下一个小例子:

  • proxy_cache_path /data/cache keys_zone=niyueling:10m loader_threshold=300 loader_files=200;

在这个例子中缓存迭代加载可以持续300毫秒或者直到加载满200个项目。在http节点下设置完proxy_cache_path命令,下一步在虚拟服务器配置中配置proxy_cache命令,我们可以看看proxy_cache命令的语法结构:

  • proxy_cache niyueling;

可以看到proxy_cache命令很简单,就是指定了我们刚才配置的内存区。但是这里有一点需要额外注意的是:我们刚才通过配置proxy_cache_path命令的keys_zone参数配置内存区大小为10m,这并不会限制缓存数据的大小,实际上缓存数据是存储在文件系统中的特定文件的元数据副本。如果想要限制缓存数据的上限,则需要在proxy_cache_path命令中添加max_size参数设置缓存数据上限。说完了proxy_cache命令。我们接着看看下一个命令:proxy_cache_methods,我们看下该命令语法结构:

  • proxy_cache_methods[GET HEAD POST];

在虚拟服务器下配置proxy_cache_methods命令可以指定该虚拟服务器下什么类型的HTTP方法可以被缓存。默认情况下GET请求及HEAD请求会被缓存,而POST请求不会被缓存。接下来看看另外一个常见的命令:proxy_cache_valid,先贴下该命令语法结构:

  • proxy_cache_valid reply_code [reply_code...] time;

这个命令很有意思,在虚拟服务器下设置该命令,它可以针对不同状态码的响应数据设置不同的缓存时间,我们可以看个简单的小例子:

  • proxy_cache_valid 200 10m ;
  • proxy_cache_valid 404 1m ;
  • proxy_cache_valid 302 5m ;

我们通过上面的命令就可以设置200状态码的缓存时间为10分钟,302重定向的缓存时间为5分钟,404的缓存时间为1分钟。如果想为所有状态码定义相同缓存时间,就可以使用any作为第一个参数:

  • proxy_cache_valid any 5m;

接下来看看下一个命令:proxy_cache_bypass。一样先看下语法结构:

  • proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;

这个命令可以配置不会向客户端响应缓存,而是直接将请求转发给后端服务进行请求数据。可以通过上述命令配置需要绕过缓存的请求URL,也就是说URL中包含该配置的值,则这次请求会直接跳过缓存直接请求后端服务去获取数据。接下来还有最后一个比较常用的命令:proxy_cache_min_uses。先贴下语法结构:

  • proxy_cache_min_uses 2;

这个命令可以设置当某请求最少响应几次后会被缓存。若我设置为2则表示每个请求最少被请求2次后会加入到缓存中。

Nginx清除缓存
如果缓存过期则需要从缓存中删除过期的缓存文件,防止新旧缓存出现交错出错,当Nginx接收到自定义HTTP头或者PURGE请求时,缓存将会被清除。

配置缓存清除
我们在HTTP节点下创建一个新变量$purge_method来标识使用PURGE方法的请求并删除匹配的URL。

http {
map $request_method $purge_method {
PURGE 1;
default 0;
}
}

进入虚拟服务器配置,在location中配置高速缓存,并且指定缓存清除请求命令proxy_cache_purge。

server {
listen 80;
server_name www.niyueling.cn;
location / {
proxy_cache niyueling;
proxy_cache_purge $purge_method;
}
}

发送清除命令

配置proxy_cache_purge指令后需要发送PURGE请求来清除缓存。例如我们使用PURGE方式请求url:

  • PURGE www.niyueling.cn/getArticle

则getArticle对应的缓存中的数据将被删除。但是,这些高速缓存数据不会从缓存中完全删除,它们将保留在磁盘上,直到它们被删除为非活动状态,或由缓存清除进程处理。

限制IP访问清除命令

清除缓存这种命令一般需要权限才可进行操作,所以我们一般需要配置允许发送缓存清除请求的IP地址:

geo $purge_allowed {
default 0;
49.235.28.88 1;
192.168.1.100/24 1;
}
map $request_method $purge_method {
PURGE $purge_allowed;
default 0;
}
当Nginx接收到清除缓存请求时,Nginx检查客户端IP地址,若IP地址已经获得清除缓存权限,则$purge_method设置为$purge_allowed,值为1表示允许清除缓存,值为0表示表示IP地址未获得权限。

从缓存中完全删除文件

刚才说过了高速缓存数据不会从缓存中完全删除,它们将保留在磁盘上,直到它们被删除为非活动状态,或由缓存清除进程处理。要完全删除与getArticle相匹配的缓存数据,需要在proxy_cache_path添加参数purger,该参数表示永久的遍历所有缓存条目,并删除与通配符相匹配的条目。

  • proxy_cache_path /data/cache keys_zone=niyueling:10m purger=on;

字节缓存
当我们请求一个大文件时,因为请求比较耗时,当有下一个请求来临时将不得不等待整个大文件被下载并放入高速缓存。Nginx用缓存片模块填充高速缓存。可以将大文件分为较小的切片,每个范围请求选择将覆盖所请求范围的特定切片,并且如果此范围切片仍未缓存,就将其放入缓存中。启用字节范围缓存需要注意两个条件是否满足:

  • 确保Nginx是使用模块编译的。
  • 使用slice指令指定切片的大小。

可以使用slice命令指定切片大小:

location / {
slice 1m;
}

使用slice指令指定切片大小时应注意切片大小应适当调整,使切片快速下载。因为切片大小指定太小可能会导致内存使用量过多和大量打开的文件描述符,切片大小指定太大的值可能会导致请求延迟。

接着将$slice_range变量加入到缓存键中:

  • proxy_cache_key $uri$is_args$args$slice_range;

使用206状态代码缓存响应,缓存有效期30m:

  • proxy_cache_valid 206 30m;

然后设置Range头传递$slice_range变量来将传递范围请求:

  • proxy_set_header Range $slice_range;

字节缓存小案例:

location / {
slice 1m;
proxy_cache niyueling;
proxy_cache_key $uri$is_args$args$slice_range;
proxy_set_header Range $slice_range;
proxy_cache_valid 206 30m;
}

缓存清除小案例

http {
proxy_cache_path /data/cache keys_zone=niyueling:10m purger=on;
map $request_method $purge_method {
PURGE 1;
default 0;
}

server {
listen 80;
server_name www.niyueling.cn;
location / {
proxy_cache niyueling;
proxy_cache_purge $purge_method;
}
}

geo $purge_allowed {
default 0;
49.235.28.88 1;
192.168.1.100/24 1;
}

map $request_method $purge_method {
PURGE $purge_allowed;
default 0;
}
}

如果喜欢我的文章,欢迎关注公众号:程序猿周先森。

Nginx缓存原理及机制的更多相关文章

  1. nginx缓存原理

    一.HTTP字段理解 1.Expires: 该字段的http1.0时的规范,值为一个绝对时间的GMT格式的时间字符串,代表缓存资源的过期时间,在这个时点之前即命中缓存. 缺点:服务器返回的时间,可能与 ...

  2. nginx 缓存机制

    nginx 缓存机制   Nginx缓存的基本思路 利用请求的局部性原理,将请求过的内容在本地建立一个副本,下次访问时不再连接到后端服务器,直接响应本地内容 Nginx服务器启动后,会对本地磁盘上的缓 ...

  3. Nginx作为静态资源web服务之缓存原理

    Nginx作为静态资源web服务之缓存原理 大致理一下http浏览器缓存原理: 浏览器第一次请求服务器,此时浏览器肯定没有缓存,则直接调用服务器端,服务器在返回的信息的信息头中添加 ETag和Last ...

  4. ahjesus 前端缓存原理 转载

    LAMP缓存图 从图中我们可以看到网站缓存主要分为五部分 服务器缓存:主要是基于web反向代理的静态服务器nginx和squid,还有apache2的mod_proxy和mod_cache模 浏览器缓 ...

  5. Nginx实现负载均衡&Nginx缓存功能

    一.Nginx是什么 Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器.Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambl ...

  6. (转)Apache和Nginx运行原理解析

    Apache和Nginx运行原理解析 原文:https://www.server110.com/nginx/201402/6543.html Web服务器 Web服务器也称为WWW(WORLD WID ...

  7. nginx 缓存,大文件分片请求方法

    实现的途径:expire cache-control 更新缓存的机制 如何校验本地缓存是否过期 expires cache-control(max-age)如果超期,说明失效 然后进行etag是否过期 ...

  8. nginx 缓存设置

    浏览器缓存原理 浏览器缓存 HTTP协议定义的缓存机制(如:Expires:Cache-control等) 2.浏览器无缓存 3.客户端有缓存 校验过期机制 校验是否过期                ...

  9. 009.Nginx缓存及配置

    一 浏览器缓存 1.1 缓存概述 缓存对于Web至关重要,尤其对于大型高负载Web站点.Nginx缓存可作为性能优化的一个重要手段,可以极大减轻后端服务器的负载.通常对于静态资源,即较少经常更新的资源 ...

随机推荐

  1. Kaggle比赛(二)House Prices: Advanced Regression Techniques

    房价预测是我入门Kaggle的第二个比赛,参考学习了他人的一篇优秀教程:https://www.kaggle.com/serigne/stacked-regressions-top-4-on-lead ...

  2. MonkeyRunner 第一天

    1.安装集成Android SDK的环境(如Eclipse),主要是为了android的模拟器,安装python编译环境,MonkeyRunner是基于Jython 2.使用Eclipse打开Andr ...

  3. docker安装到基本使用

    记录docker概念,安装及入门日常使用 Docker安装(Linux / Debian) 查看官方文档,在Debian上安装Docker,其他平台在这里查阅,以下均在root用户下操作,省去sudo ...

  4. java多线程----悲观锁与乐观锁

    java多线程中悲观锁与乐观锁思想 一.悲观锁 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线 ...

  5. Mybatis延迟加载的实现以及使用场景

    首先我们先思考一个问题,假设:在一对多中,我们有一个用户,他有100个账户. 问题1:在查询用户的时候,要不要把关联的账户查出来? 问题2:在查询账户的时候,要不要把关联的用户查出来? 解答:在查询用 ...

  6. Spring自定义属性编辑器及原理解释.md

    bean的自动装配解释 手动解决方式 自动注入解决方式 bean的自动装配解释 之前有构造注入和设值注入,但是也是手动的 autowire ="byname" 这里要注意自动装配的 ...

  7. pytest-html报告修改与汉化

    前言 Pytest框架可以使用两种测试报告,其中一种就是使用pytest-html插件生成的测试报告,但是报告中有一些信息没有什么用途或者显示的不太好看,还有一些我们想要在报告中展示的信息却没有,最近 ...

  8. JS函数提升和变量提升

    1.1什么是函数提升和变量的提升? JS引擎在运行整个JS代码的过程中,分为俩步. 第一步是读取和解析JS代码,第二部是执行. 在引擎解析JS代码的时候,当解析器遇见变量声明(var 变量名)和函数声 ...

  9. “adobe premiere中画面和声音不同步” 解决方法

    一.背景 之前在segmentfault上过直播课,直播课有录制回播功能:尝试听了下直播课,发现视频太长了,感觉听起来非常花费学员的时间,在回放中其实有一些直播课里面的内容并不需要,所以准备剪辑一下, ...

  10. MySQL5.7.27报错[Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated

    mysql5.7.27在运行更新语句时出现如下情况,mysql5.6之前没有这种情况出现. of ORDER BY clause is not in GROUP BY clause and conta ...