Nginx缓存机制和性能优化

Posted 踩踩踩从踩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nginx缓存机制和性能优化相关的知识,希望对你有一定的参考价值。

目录

Nginx缓存机制介绍

Nginx缓存机制的作用

nginx缓存机制简述

 Nginx缓存支持

 缓存使用

proxy_cache_path参数详解

 缓存清除机制分析

被动缓存清除

缓存加载

主动清除缓存

Nginx程序运行原理分析

Nginx工作模式

多进程处理模型

多进程处理模型优点

Nginx为何要采用多进程模式?

Worker进程遇到的问题

解决

Worker与CPU的绑定

linux服务器参数调整 

修改配置文件

调整内容

生效配置

Nginx常规调整


nginx缓存机制介绍

Nginx中如何使用缓存,缓存机制是怎么样的。而且Nginx缓存是不会像redis这些一样有自己的内存管理机制,池化等,它会依据文件系统进行缓存

Nginx缓存机制的作用

  • 缓存能够提升性能,学会Nginx中如何使用缓存很重要。
  • Nginx作为静态资源服务器,静态资源变动频率小,缓存能够加速访问。
  • Nginx离用户最近,启用缓存能更好的提高性能,结合Redis可以组成类似二级缓存。

nginx缓存机制简述

Nginx中的缓存
nginx中的缓存是以文件系统上的分层数据存储的形式实现的。
缓存Key是可配置的,并且可以使用不同的请求特定参数来控制进入缓存的内容。
缓存Key和缓存元数据存储在 共享内存段中,缓存加载器、缓存管理器和Worker进程可以访问它 们。目前,除了操作系统的虚拟文件系统机制所暗示的优化之外,没有任何内存中的文件缓存。每个缓存的响应都放在文件系统上的不同文件中。通过nginx配置指令控制指定层次结构(级别和命名细节)。

nginx是没做优化的。

缓存放置内容过程:
当nginx从上游服务器读取响应时,首先将内容写入缓存目录结构之外的临时文件。
当nginx完成处理请求时,它会重命名临时文件并将其移动到缓存目录。如果用于代理的临时文件目录位于另一个文件系统上,则文件将被复制,因此建议将临时目录和缓存目录保留在同一个文件系统上。当需要显式清除文件时,从缓存目录结构中删除文件也是非常安全的。
nginx有第三方扩展,可以远程控制缓存的内容,并计划在主发行版中集成此功能

 

 Nginx缓存支持

Nginx中有非常强大的缓存功能,针对后台服务返回的数据能够进行缓存,再次访问时,无需从台服务拿取结果,直接在nginx本地获取即可。Nginx中针对fastcgi、http_proxy、scgi、ssl_session、ngx_http_uwsgi_module模块提供了通用的缓存功能。
file cache 文件缓存。
以http_proxy模块为例来进行讲解,观察官网其他模块,都相差不大,学会一个其他的也就学会了 

在官网中api模块 设置,  都有自己的默认值,可以根据需要设置。

 缓存使用

 在配置文件中。 主要是在http指令块中存在

包括代理缓存配置,定义的配置  

events {
	# 并发连接数
    worker_connections  1024;
}
http {
    # JAVA服务器集群
	upstream app_servers {
		server 127.0.0.1:8080;	
#		server 127.0.0.1:8081;
	}
	# 代理缓存配置 - 定义配置
	proxy_cache_path "./cache_data/" levels=2:1:2 keys_zone=hot_information_cache:256m inactive=1d max_size=1000g;  
	proxy_cache_path "./cache_data/" levels=2:1:2 keys_zone=cache2:256m inactive=30s max_size=30g;  
	server {
		# 监听80端口
		listen	80;
		location / {
            # 开启缓存
            proxy_cache hot_information_cache;
            # 缓存JAVA应用返回的指定状态的数据,缓存时间时1天       
            proxy_cache_valid 200 206 304 301 302 1d;
            # 请求的url就是缓存的key(根据实际业务场景匹配)       
            proxy_cache_key $uri$is_args$args;      
            
            # 设置传递给上游服务的请求头,Host为客户端host,默认为$proxy_host
            proxy_set_header Host $http_host;
            # 如果缓存中没找到,再去请求后端服务器
            proxy_pass http://app_servers;
		}
		
		# 该指令在商业版本Nginx Plus支持,可以通过第三方模块ngx_cache_purge来替代
		# 资源有变化的时候清除缓存
		location ~ /purge(/.*) {
			#设置只允许指定的IP来清除缓存
			allow all;
			# allow 127.0.0.1;
			# deny all ;
			proxy_cache_purge hot_information_cache $1;
		}
	}
}

levels表示目录层级 3级。

 后面对应的参数,包括proxy_cache_path 缓存的路径 和缓存空间名、大小等配置。启用缓存proxy_cache 等。

proxy_cache_path 可以配置多个的。

 keys_zone=cache2:256m  这里定义的是 空间名称 和大小。

proxy_cache_valid  缓存JAVA应用返回的指定状态的数据,缓存时间时1天

proxy_cache_key  请求的url就是缓存的key  

proxy_set_header  设置传递给上游服务的请求头。

通过这些指令 可以开启缓存。

proxy_cache_purge   进行对 数据进行清除,定义将请求视为缓存清除请求的条件。如果字符串参数的至少一个值不为空且不等于“0”,则移除具有相应高速缓存键的高速缓存条目 。通过返回204(无内容)响应来指示成功操作的结果。
对于缓存来说,首先存在内存中,只有内存满了,会存在磁盘中

proxy_cache_path参数详解

level
用来定义缓存的层级,可以定义1到3个层级,每个层级接收值1、2
use_temp_path
是否启用缓存临时文件,第一次响应的内容将写入临时文件,后面才会重写回来。使用网盘注意网络 IO的开销。
keys_zone
定义在共享存储区中存储了所有活跃的Key和关于数据的信息。存储区名称和大小由key_zone参数配置。 一个兆字节的区域可以存储大约8,000个Key
Inactive
不论数据新旧程度,在inactive指定的时间内未访问的缓存数据 将从缓存中删除。

 缓存清除机制分析

 对于内存和磁盘满了,nginx如何清除的,以及会不会像redis去池化会不会有碎片化的处理。

缓存自己有缓存管理进程 

被动缓存清除

proxy_cache_path 指令的缓存管理

   proxy_cache_path 中可以通过以下指令来管理缓存

  • max_size  指定缓存大小,缓存管理进程监控缓存是否超过指定值,超过该大小则通过LRU算法来 淘汰数据。一次迭代删除的数据通过下面的参数来指定。
  • manager_files 一次迭代过程中删除的项的数量,默认100个
  • manager_threshold 一次迭代操作的持续时间限制,默认200毫秒
  • manager_sleep 两次迭代的间隔时间,默认50毫秒

缓存加载

proxy_cache_path中可以通过以下参数来调整加载缓存 Nginx启动一分钟后,缓存加载进程被激活,存储在文件系统上先前缓存的数据将被加载到 缓存区中,整个加载是在迭代中完成的。一次加载

  • loader_files 一次迭代加载不超过指定数目的项,默认100。
  • loader_threshold 一次迭代操作的持续时间限制,默认200毫秒
  • loader_sleep 两次迭代的间隔时间,默认50毫秒

主动清除缓存

Nginx商业功能

proxy_cache_path中可以通过以下参数来调整主动清除缓存

  • purger:on开启缓存清除进程,遍历所有缓存条目并删除匹配到的键的缓存数据
  • purger_files   一次迭代过程中扫描的项的数量,默认10个
  • purger_threshold   一次迭代的持续时间,默认50毫秒
  • purger_sleep  两次迭代的间隔时间,默认50毫秒
以上参数与proxy_cache_purge指令配合进行。
虽说只能在商业版的Nginx中使用,但是我们可以通过强大的第三方模块来替代

该指令在商业版本Nginx Plus支持,可以通过第三方模块ngx_cache_purge来替代

location ~ /purge(/.*) {
			#设置只允许指定的IP来清除缓存
			allow all;
			# allow 127.0.0.1;
			# deny all ;
			proxy_cache_purge hot_information_cache $1;
		}

ngx_cache_purge是一个第三方的nginx缓存主动清除模块,集成方便,使用简单。下面我们就来学习如何安装使用它。本节内容基于第一课安装的Nginx基础进行,这里我们只是再编译增加模块。

Nginx缓存主动清除插件ngx_cache_purge 提取码:d8eq

Nginx程序运行原理分析

nginx在运行时,架构是怎么样的,架构 工作模式;从进程来看有 master  和worker进程。

Nginx工作模式

Nginx在启动时会以daemon形式在后台运行,采用多进程+异步非阻塞IO事件模型来处理各种连接请求。多进程模型包括 一个master进程,多个worker进程,一般worker进程个数是根据服务器CPU核数来决定的。master进程负责管理Nginx本身和其他worker进程。
4个worker进程的父进程都是master进程,表明worker进程都是从父进程fork出来的,并且父进程的ppid为1,表示其为daemon进程。
Nginx中的Master、Worker两种进程。
Master进程
        负责加载配置、接收命令、监控子进程。Master进程也是可以关闭的
Worker进程
                负责处理网络请求。Worker进程的个数由配置文件决定,一般和CPU个数相关(有利于进程切换),配置几个就有几个Worker进程。需要说明的是,在nginx多进程中,每个worker都是平等的,因此每个进程处理外部请求的
机会权重都是一致的。
按理来说 worker进程处理请求的机会是一样的。

这个流程模型和netty上的网络模型,都是很像的,网络请求。

多进程处理模型

多进程模型的处理方式  

  • 首先,master进程一开始就会根据我们的配置,来建立需 要listen的网络socket fd,然后fork出多个worker进程。
  • 其次,根据进程的特性,新建立的worker进程,也会和 master进程一样,具有相同的设置。因此,其也会去监听 相同ip端口的套接字socket fd。
  • 然后 ,多个worker进程监听同样设置的socket fd,当有 一个请求进来,所有的worker都会感知。
  • 最后 ,监听成功的worker进程,读取请求,解析处理,响 应数据返回给客户端,断开连接,结束。因此,一个request请求,只需要worker进程就可以完成。

     

多进程处理模型优点

Nginx为何要采用多进程模式?

  • 进程之间是独立的,当一个worker进程出现异常退出,其他worker进程不会受到影响;
  •  独立进程也会避免一些不需要的锁操作,这样能提高处理效率,开发调试也更容易。
单纯的 多进程模型会导致连接并发数量降低 异步非阻塞IO模型 能解决这个问题,还能避
多线程上下文切换导致 的性能损失。
多进程模型+异步非阻塞模型是一个非常好的选择。
跟NIO、Netty线程模型思想一致,只不过一个是线程级、一个是进程级。

Worker进程遇到的问题

出现惊群效应
多个worker子进程监听相同端口的设计,这样多个子进程在accept建立新连接时会有争抢,这会带来 著名的“惊群”问题,子进程数量越多问题越明显,这会造成系统性能下降。建立新连接时Nginx是如 何避免出现“惊群”现象的呢?
Worker进程负载不均衡
多个子进程争抢处理一个新连接事件,最终只有一个worker子进程成功建立连接,随后,它会一直处 理这个连接直到连接关闭。
如果有的子进程很“勤奋”,它们抢着建立并处理了大部分连接,而有的子进程则“运气不好”,只 处理了少量连接。

解决

Nginx 的 Post队列
将epoll 产生的事件分开,新连接事件的
  • ngx_posted_accept_events队列优先执行,普通事件的
  • ngx_posted_events队列最后执行

 accept_mutex

Nginx采用了一个是否打开accept_mutex选项的值,控制worker进程是否需要去竞争锁,打开accept_mutex锁,能很好解决accept精确问题

ngx_accept_disabled
worker进程进行负债均衡阈的判断值,处理的连接总数没有达到7/8,不会抢accept锁,达到时,则需要枪锁,它解决了负载均衡的问题。

 

 这是module中代码。

Worker与CPU的绑定

Worker进程跟CPU个数有关,但是如果多个Worker进程在同一个CPU上面争夺资源也非常消耗性能。Nginx中有一个 worker_cpu_affinity 配置,能够将worker绑定到对应的CPU上面。
单个Worker进程处理的并发连接数配置

linux服务器参数调整 

当TCP TIME_WAIT套接字数量经常达到两、三万,服务器很容易被拖死,需要减少Nginx服务器的TIME_WAIT套接字数量。
这个和netty对于服务器参数调整是一样的,都是例如统同时保持TIME_WAIT套接字的最大数量,以及最大连接数等等。

修改配置文件

sudo vim /etc/sysctl.conf

调整内容

# 表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
# 由于某种原因服务端主动关闭连接,连接进入FIN_WAIT2状态,该状态是没有超时的
# 如果客户端不关闭,这个FIN_WAIT_2状态将保持到系统重新启动,越来越多的FIN_WAIT_2状态会致使内核crash
net.ipv4.tcp_fin_timeout = 30
# 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.tcp_keepalive_time = 1200
# 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,
# 可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_syncookies = 1
# 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1
# 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_tw_recycle = 1
# 表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。
net.ipv4.ip_local_port_range = 1024    65000
# 表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_syn_backlog = 8192
# 表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。默认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。
net.ipv4.tcp_max_tw_buckets = 5000

生效配置

sudo /sbin/sysctl -p

Nginx常规调整

以上是关于Nginx缓存机制和性能优化的主要内容,如果未能解决你的问题,请参考以下文章

Nginx一网打尽:动静分离压缩缓存黑白名单跨域高可用性能优化......

Nginx一网打尽:动静分离压缩缓存黑白名单跨域高可用性能优化......

浏览器缓存机制与Nginx配置调优

如何利用Nginx的缓冲缓存优化提升性能

H5缓存机制浅析-移动端Web加载性能优化干货

9.4 代码缓存 Java性能优化节选