nginx性能优化思路及实践

一、优化思路

关于nginx作为web服务器优先的方案可从两方面考虑,一个是nginx配置的优先,让nginx的这个软件与硬件达到最大的协调。另外一个是对操作系统的优化,让系统的提供最优的服务,主要是系统资源上的限制优化,特别是关于tcp方面的优化。(如果是用动态语言如php构建的网站,还需要对php的配置进行优化,当然php的优化与linux的优化并不在nginx优化的内容这中,但却与nginx优化有着深层次的联系,如果系统资源限制,则nginx即使做了最优的配置,也无法发挥其作用)

1、nginx配置优化
  • (1)worker_processes 工作进程数。(nginx的进程分主进程和工作进程,主进程主要是为工作进程分配任务的,而工作进程才是具体处理任务的,主进程就是老板或者主管,工作进程就是小兵,像我们这些一线的码农)

一般来说工作进程数,应该与服务器的cpu核数有关,基本上它的个数应该等于CPU的个数CPU的核数,也有人认为应该比CPU的个数CPU的核数少一个,因为还有一个主进程需要一占用一个

那如何cup信息呢?

  1. cat /proc/cupinfo

其实服务器的物理cpu的个数是根据physical id来计算的,因此查看服务器的cpu个数:

  1. cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l

服务器的cput核数是根据cpu cores这个来标识的,因此查看服务器的每个cpu的核数:

  1. /proc/cpuinfo |grep "cores"|uniq

修改工作进程数

  1. user nobody;
  2. #其他配置省略
  3. worker_processes 4;
  • (2)使用epoll事件处理模型
  1. event {
  2. #其他配置省略
  3. use epoll;
  4. }
  • (3)适当配置工作进程连接数worker_connections
  1. event {
  2. #其他配置省略
  3. worker_connections 65535;
  4. }
  • (4)打开个新的连接后接收尽可能多的连接
  1. event {
  2. multi_accept on;
  3. }
  • (5)关闭访问日志,减少磁盘读写操作(在调试阶段可开启)
  1. http {
  2. #省图其他配置
  3. access_log off;
  4. #省略其他配置
  5. }
  • (6)设置合适的客户端请求体大小(在上传一个比较大的文件时,如果超过这个值会出现413的错误)
  1. http {
  2. #其他配置
  3. client_max_body_size 50m;
  4. #其他配置
  5. }
  • (7)启用gzip压缩,减少响应体的大小。

特别是对于文本文件,启用gzip可以极大减少响应内容的大小,从而在一定程度上加快响应速度

  1. http {
  2. #其他配置省略
  3. gzip on;
  4. gzip_comp_level 5;
  5. gzip_types text/plain text/css text/javascript;
  6. gzip_buffers 8 4k;
  7. #其他配置省略
  8. }
  • (8)设置keepalive的超时时间,这个数据尽可能小
  1. http {
  2. #其他配置
  3. keepalive_timeout 20s;
  4. #其他配置
  5. }
  • (9)开启打开文件描述的缓存:设置缓存的大小和缓存时间
  1. http {
  2. #其他配置省略
  3. open_file_cache max=10000 inactive=60s;
  4. #其他配置省略
  5. }
  • (10)启用sendfile(默认也是开启的):作用是将立即将数据从硬盘读入到OS缓存中
  1. http {
  2. #其他配置
  3. sendfile on;
  4. #其他配置
  5. }
  • (11)适应修改工作进程打开的文件描述数目
  1. http {
  2. #其他配置省略
  3. worker_rlimit_nofile 55535;
  4. #其他配置
  5. }
2、linux系统优化
(1)卸载不必要的软件和关闭不必要的服务

比如一台web服务器,只安装web相关的软件以及相关联的支持库,开启必须使用到的服务,其他的则关闭。

(2)优化写磁盘操作:减少对硬盘的写操作

nginx在访问一个文件时,系统都会修改这个文件的访问时间即(access),我们可以通过stat这个命令来查看:

  1. stat /usr/local/nginx/html/index.html

所以关闭这个功能,可以减少对磁盘的写操作

  • 首先、我们要查看我们的分区情况,知道web根目录在哪个分区,我的在/usr/local/nginx/html下面
  1. df -h

所以看出我的web根目录就在 /dev/mapper/VolGroup-lv_root 这个分区

  • 其次,在/etc/fstab这个文件中关闭修改文件访问时间的功能:
  1. vim /etc/fstab

看到这样一行内容:

  1. /dev/mapper/VolGroup-lv_root / ext4 defaults 1 1

我们把它修改成:

  1. /dev/mapper/VolGroup-lv_root / ext4 defaults ,noatime,nodiratime 0 0
  • 最后,我们重启系统或者重新挂载(具体的要看你的web所在目录的挂载点)
  1. mount -o remount /;
(3)优化资源限制:ulimit
  1. ulimit -n #查看单个用户对文件描述符的使用限制数
  2. ulimit -u #查看单个用户最多可使用的进程数

重新设置一下:

  1. ulimit -n 65535;
  2. ulimit -u 65535;

这种设置如果在重启系统后会失效,如果想设置永久有效,则需要修改/etc/security/limits.conf

增加如下几行:

  1. * soft nofile 65535
  2. * hard nofile 65535
  3. * soft nproc 65535
  4. * hard nproc 65535
# (4)优化TCP内核参数:

具体方法有两种:

  • 第一种,直接通过文件重定向的方向修改/proc下面的相关参数对应的文件的值
  • 另外一种是通过修改/etc/sysctl.conf来实现,个人比较喜欢第2种,一是它是永久的,二是它比较方便。

我们先编加:/etc/sysctl.conf文件 ,如果文件中没有以下参数则添加,如果有以下参数则修改,是后修改完以后保存,如果想立即生效,则使用如下systcl -p命令。

  1. #设置timewait的值(该配置项用来防范简单的DoS攻击 ,在某些情况下,可以适当调大,但绝对不应调小)
  2. net.ipv4.tcp_max_tw_buckets = 6000
  3. #设置系统允许打开的端口的范围
  4. net.ipv4.ip_local_port_range 1024 65000
  5. #是否启用timewait快速回收
  6. net.ipv4.tcp_tw_recycle =1
  7. #是否复用timewait连接
  8. net.ipv4.tcp_tw_reuse =1
  9. #是否启用syn cookies,当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭
  10. net.ipv4.syncookies=1
  11. #socket最大连接数
  12. net.core.somaxconn=262144
  13. #表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
  14. net.ipv4.tcp_max_syn_backlog=262144
  15. #设置使用时间戳作为序号
  16. net.ipv4.tcp_timestamps=0
  17. #设置syn重试次数
  18. net.ipv4.tcp_synack_retries=1
  19. #设置内核放弃建立连接之前发送syn包的数量
  20. net.ipv4.tcp_syn_retries=1
  21. #设置FIN_WAIT_2状态的时间
  22. net.ipv4.tcp_fin_timeout=1
  23. #设置tcp发送keepalive消息的时间
  24. net.ipv4.keepalive_time =30

二、nginx优先实践

  • 1、实验结果作对比:

之前用ab进行压力测试时,200机器的最大并发数为2000,最大请求数为10000

  • 2、我们对nginx和内核进行优化后再来看一下:

发现当10000并发,请求数为10000时很轻松,当然将请求数调整到30000时会出现超时情况,这些可能是硬件有关了。