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

上篇文章介绍了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. [SCOI2009]粉刷匠(动态规划,序列dp,背包)

    分别对每块木板做区间dp,设\(g[i][j]\)表示前i个格子,刷恰好j次,并且第i格是合法的最多合法的格子数.从前往后枚举断点来转移就好了. 这样处理再出来\(g[i][j]\)每一块木板i刷j次 ...

  2. Day 07--最终修改(三)

    2.明天着重学一下逻辑层的语法,以及界面层的数据绑定,与队友交流进度 3.今天修改也终于完成,除了搞c++以外的全部身心都放在这个东西身上也觉得它有点难搞,说明计算机不是吃素的.甚至在使用xml语法的 ...

  3. F#周报2019年第34期

    新闻 高效的F#,提示与技巧 Fable 社区资源 Visual Studio提示与技巧:为.NET增加生产力 无风险地尝试Compositional IT的培训包--如果没有增加任何价值,可以得到完 ...

  4. Swoole引擎原理的快速入门干货

    更多内容,欢迎关注微信公众号:全菜工程师小辉~ 过去一年使用PHP和Java两种技术栈完成了一个游戏服务器项目.由于项目中有高频的网络请求,所以PHP技术栈尝试使用Swoole引擎(基于事件的高性能异 ...

  5. Vim高手,从来不用鼠标

    Vim脱离鼠标第一步 平时不可缺少的会用到vim,但是避免不了鼠标,事实上,省略鼠标是完全可以的,没有想像中那么难,看我短短几行带大家一起省略鼠标. 对了,vim有三种模式,基本模式就是用来输入命令的 ...

  6. Spring数据库连接

    1.C3P0数据库连接 2.DBCP数据库连接 3.Druid数据库连接 C3P0数据库连接: 1.先到(http://www.mvnrepository.com/)Maven网址找到C3P0的数据源 ...

  7. C#窗体--鼠标事件

    常见的鼠标事件: mouseclick,mousedown,mouseup,mousuenter,mouseleave.mousemove mouseDown按下鼠标事件: //鼠标按下后显示 pri ...

  8. abp(net core)+easyui+efcore实现仓储管理系统——菜单 (十六)

    系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+easyui+efcore实现仓储管理系统——解决方案介绍(二) ...

  9. 带你了解什么是Push消息推送

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 如果有看我最近文章的同学可能就知道我在公司负责的是一 ...

  10. docker进阶1-命令补充和容器卷使用

    命令补充 docker信息与帮助 docker version 和 docker info docker --help 查看所有docker命令列表 docker --help run/commit/ ...