Nginx高性能优化配置实战总结

相信做过web的同学对于 Nginx 一定不陌生,它是一款轻量级的开源 Web 服务及代理程序 。在 Nginx 出现之前市场上主流两款 Web 服务,一款是 IIS,另外一款是 Apache 。而在 Nginx 诞生后,因其轻量化、支持高并发等特性,逐渐蚕食了这两款 Web 服务的市场份额 。目前国内大量企业已经广泛使用 Nginx 。那么我们在工作中如何对其进行优化和配置便成了重中之重 。
在学习如何优化和配置 Nginx 之前,首先需要提前掌握一些基础知识,包括:

  • 熟悉linux 的基础操作;
  • 了解 Nginx 安装和基础配置;
  • 对 HTTP 请求过程有一定了解 。
Nginx 的优化主要分为基础优化和缓存优化,我们先来看一下基础优化 。
基础配置优化主要包括:
  • CPU 亲和性优化;
  • Nginx 模型优化;
  • Nginx 传输方式优化;
  • Nginx 文件压缩优化 。
在 Nginx 用于普通的绝大部分 Web 服务时这些优化场景都是需要了解的 。
CPU 亲和性所谓的 CPU 亲和性是做什么呢?现在的CPU通常都是多核的,而且可以通过超线程来虚拟更多核数 ,那亲和力就是让 Nginx 充分发挥多核 CPU 的性能,从而提高 Nginx 的服务性能 。Nginx 运行时会启用 1 个 master 进程及多个 worker 进程,worker 进程负责处理请求,如果 worker 进程在多核 CPU 中发生频繁的调度切换就会损耗性能 。在这种情况下,我们希望减少这种频繁调度,让每一个 Nginx 的 worker 线程都能够固定到具体的 CPU 核心上,所以就需要配置 Nginx 的 CPU 亲和性来解决这个问题 。
由于 Nginx CPU 亲和性配置本身有多套配置方案,这里推荐我们推荐直接将配置项设置成 auto(worker_cpu_affinity ),即采用了 Nginx 推荐的 CPU绑核策略方式 。另外的一个方式是手动绑定,将 worker 线程数量与 CPU 核数一一绑定方式设置 。我们设置成 auto Nginx 会自动识别并按照推荐策略来分配 worker 线程和 CPU 。
Nginx高性能优化配置实战总结

文章插图
 
如图所示,我们看到 CPU 的核心有 8 个,如果我们设置成 auto 后,那么 Nginx 会将 8 个 worker 线程一对一地按照推荐策略绑定到 CPU 核心上,这样避免 CPU 频繁对 worker 线程进行调度,从而降低 CPU 损耗 。
IO 流事件模型Nginx 第二个基础配置优化项是 IO 流事件模型,我们经常可以在 Nginx 下面看到的 events 配置模块中默认设置了 use epoll,表示 Nginx 使用 epoll 这个 IO 流事件模型,那为什么 Nginx 会选择使用 epoll 呢?这是因为 epoll 有以下这些得天独厚的优势 。我们来详细讲解一下:
首先,Linux 系统下一切皆文件,比如我们打开一个设备,它便会产生一个文件描述符 。在产生一个进程时,这个进程便需要一个进程描述符,这个进程描述符也是一个文件 。所以在 Nginx 处理请求的时候,每一个请求都会产生处理请求的描述符 。
其次,在 Nginx 处理大规模请求的时候,为了提高并发效率需要采用异步非阻塞模型,这又和 epoll 有什么关系呢?epoll 本身是以异步非阻塞模型来处理请求流中的事件流 。
这里还需要注意一点,并不是所有的 Linux 操作系统都可以使用 epoll,它是在 kernel 2.6 版本以后提出的,早期内核使用的 selectpoll 模型,select 模型比 epoll 模型性能要低很多,有经验的运维同学一定深有体会 。
那么 epoll 相比于 select 模型到底具备哪些优势呢?
  • epoll 处理事件流模型是线程安全的;
  • epoll 跟 select 模型相比调用 fd 文件描述符时使用了 mmap 共享用户和内核的部分空间,提高了效率;
  • epoll 是基于事件驱动的,相比 select 需要扫描整个文件描述符的相关状态,epoll 基于事件驱动避免频繁扫描文件描述符,可以直接调用 callback 回调函数,效率更高;
  • 取消了 select 模型里面单个进程能够监视的文件描述符的数量存在的最大限制(1024),如果你有使用过早期的 Apache 版本的,它使用的select 模型,当请求超过 1000 以后就会出现延迟或者请求错误,而改用 Nginx 的话性能会得到明显的改善 。
另外补充下,在 events{} 配置中还涉及一个优化的地方就是 worker_connections,这个也是在 events 里面来进行设置的,通过上面的学习我们知道了 worker 线程作用,那每一个 worker 线程所支持的连接是有限的,这里会默认设置成 1024,而我们在处理高并发的场景时,单个 worker 线程设置成 1024 的话往往偏低,这里建议你将 worker_connections 调大一些,你可以参考实际业务所需 Nginx 处理最大峰值来调大这个设置值 。


推荐阅读