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

上篇文章介绍了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. 既然synchronized是"万能"的,为什么还需要volatile呢?

    在我的博客和公众号中,发表过很多篇关于并发编程的文章,之前的文章中我们介绍过了两个在Java并发编程中比较重要的两个关键字:synchronized和volatile 我们简单回顾一下相关内容: 1. ...

  2. LoRaWAN_stack移植笔记 (二)_GPIO

    stm32相关的配置 由于例程使用的主控芯片为STM32L151C8T6,而在本设计中使用的主控芯片为STM32L051C8T6,内核不一样,并且Cube库相关的函数接口及配置也会有不同,所以芯片的驱 ...

  3. DIY显示器篇------DIY教程

    前言: DIY显示器是这几年才火起来的,或者说这几年在游戏圈火起来的.我第一次看到是在NGA上,一位玩PUBG的大佬自己DIY了一个显示器,27寸 2k 144 ips的屏幕,当时市面上只有四款显示器 ...

  4. Example With JdbcDaoSupport

    By extended the JdbcDaoSupport, set the datasource and JdbcTemplate in your class is no longer requi ...

  5. jQuery Validate 可选项

  6. jquery validate常用方法及注意问题

    1. required: true 值是必须的.required: "#aa:checked" 表达式的值为真,则需要验证.required: function(){} 返回为真, ...

  7. Mysql主从复制原理及搭建

    ## Mysql主从复制原理 主从复制是指一台服务器充当主数据库服务器,另一台或多台服务器充当从数据库服务器,主服务器中的数据自动复制到从服务器之中.对于多级复制,数据库服务器即可充当主机,也可充当从 ...

  8. 简单的JavaScript字符串加密解密

    简单的JavaScript字符串加密解密 <div> <input type="text" id="input" autofocus=&quo ...

  9. Java 并发:学习Thread 类

    Java 中 Thread类 的各种操作与线程的生命周期密不可分,了解线程的生命周期有助于对Thread类中的各方法的理解.一般来说,线程从最初的创建到最终的消亡,要经历创建.就绪.运行.阻塞 和 消 ...

  10. lua&C#学习整理

    1.Lua中有8个基本类型分别为:nil.boolean.number.string.userdata.function.thread和table. 2.pairs 和 ipairs区别 pairs: ...