1. 优化策略

1.1. 软件方面

  • 增加CPU利用率
  • 增加内存利用率
  • 加强I/O优化
  • 增加网络带宽利用率

    1.2. 硬件方面

  • 使用更高性能的网卡,如千兆网卡换万兆网卡

  • 使用更好的CPU,增加CPU性能
  • 使用更快更大的内存
  • 使用更好的固态硬盘
  • 横向扩张集群

    2. CPU部分

  • 减少非Nginx进程对CPU的消耗

  • 设置Nginx的worker进程数量等于CPU逻辑核心数
  • 将Nginx的worker进程和CPU核心进行绑定,降低上下文切换,提高缓存命中率
  • 适当提高Nginx进程的优先级
  • 大流量场景中,当软中断占比较大时,使用软中断负载均衡,平衡CPU压力
    1. worker_processes auto ; ## auto表示worker进程数和CPU核心数一致
    2. worker_cpu_affinity auto ; ## auto表示worker进程进程自动进行cpu绑定
    3. worker_priority 0 ; ## 0是默认优先级

3. 文件句柄数

3.1. 系统配置

  1. # 根据实际场景针对用户进行调整, 用户重新登录后生效
  2. [root@localhost ~]# cat /etc/security/limits.conf
  3. * soft nproc 65535
  4. * hard nproc 65535
  5. * soft nofile 655350
  6. * hard nofile 655350
  7. * soft core unlimited
  8. * hard core unlimited
  1. # 根据实际场景针对服务调整,此处修改的是默认系统配置
  2. [root@localhost ~]# vim /etc/systemd/system.conf
  3. [Manager]
  4. DefaultLimitCORE=infinity
  5. DefaultLimitNOFILE=655350:655350
  6. DefaultLimitNPROC=65535:65535
  7. # 重载sysctem.conf配置,然后再重启服务
  8. [root@localhost ~]# systemctl daemon-reexec

3.2. nginx进程限制

  1. worker_rlimit_nofile 655350 ; ## 限制所有工作进程能打开的最大文件数,一般不用设置

4. TCP连接

4.1. 内核参数配置

  1. net.core.netdev_max_backlog = 65535
  2. # 当内存处理数据包速度低于网卡接收数据包速率时,数据包会存放在缓冲区。
  3. # 此参数设置网卡缓冲区数据包队列大小,默认1000。可以适当设置大一些,如65535。
  4. net.ipv4.tcp_timestamps = 1
  5. # 在数据包中加上时间戳,针对带宽特别高的场景下,数据包中的sequence会出现重复,从而导致数据包混乱。
  6. # 一般万兆网卡设备建议开启,大流量场景下容易出现sequence重复
  7. net.ipv4.tcp_syn_retries = 2
  8. # 初次握手时,未收到服务端响应情况下,重试syn握手包次数。
  9. net.ipv4.tcp_synack_retries = 2
  10. # 二次握手时,未收到客户端响应时,服务端重试发送syn+ack包数量。建议调小一些,降低syn攻击的影响。
  11. net.ipv4.tcp_max_syn_backlog = 655350
  12. # 设置半连接队列大小,在收到syn攻击时这个值要尽可能大一些
  13. net.core.somaxconn = 655350
  14. # 系统单个socket全连接大小,适当调高用于应对高并发场景。Centos 7默认128。
  15. net.ipv4.tcp_fin_timeout=20
  16. # 断开fin_wait_2的超时时间
  17. net.ipv4.tcp_tw_reuse = 1
  18. # 启用time_wait重新利用。
  19. net.ipv4.tcp_tw_recycle = 0
  20. # 在NAT环境中,当大量客户端穿过NAT网络访问Nginx时,如果开启这个参数会导致大量数据包异常。
  21. net.ipv4.tcp_max_tw_buckets = 65535
  22. # timewait 的数量限制,如果想让timewait连接减少,适当降低这个数值即可。
  23. net.ipv4.ip_local_port_range = 10240 60999
  24. # 允许系统打开的端口限制,根据实际情况适当调整范围,一般对服务端来说影响不是很大

4.2. Nginx配置

  1. worker_connections 65535 ; ## 单个worker进程能创建的连接大小,包括与客户端连接、代理连接。
  2. use epoll ; ## 使用epoll提高高并发下Nginx处理能力
  3. listen 8080 backlog=655350 ; ## Nginx的全连接队列大小,默认511
  4. tcp_nopush on ; ## 大量小数据包场景中,积累多个数据表一起发送,提高带宽利用率
  5. keepalive_timeout 70 60 ; ## 启用长连接,让能识别header_timeout的客户端主动断开连接,可用减少timewait数量
  6. keepalive_requests 200 ; ## 提高单个长连接发送的请求数,减少长连接的重新建立,一般场景下不需要配置

5. Nginx的其它配置

5.1. 使用客户端缓存

  1. map $sent_http_content_type $expires {
  2. default off;
  3. ~image/ 3d ;
  4. ~vedio/ 7d ;
  5. text/plain 24h;
  6. text/css 24h;
  7. text/html 24h;
  8. application/javascript 24h;
  9. application/pdf 30d;
  10. application/zip 30d;
  11. }
  12. expires $expires ;
  13. ## 一般根据实际场景在对不同的文件类型设置缓存时间,在静态资源服务器中非常管用
  14. ## map是一种很好的实现方式,也可以根据不同的location来匹配

5.2. 使用gzip压缩

  1. gzip on ;
  2. gzip_comp_level 2 ; ## 根据实际情况考虑,CPU空闲资源多可用提高压缩级别
  3. gzip_disable msie6 ; ## IE 6启用压缩
  4. gzip_min_length 1024 ; ## 最小被压缩文件长度
  5. gzip_types text/css text/plain application/javascript application/xml image/gif image/jpeg image/png ;
  6. ## 在部分大文件下载场景中,可用将预压缩文件直接发送给客户端,在包含反向代理中需要考虑再哪个机器上进行压缩。
  7. gzip_static on ;

5.3. 磁盘I/O

Nginx在socket上有epoll事件驱动模型,可用非阻塞的处理socket连接,但针对普通文件而言,磁盘I/O在所难免,尤其是在静态资源服务器和缓存服务器中。

5.3.1. Nginx配置

  1. open_file_cache max=65535 inactive=30 ; ## 缓存的文件数和过期时间
  2. open_file_cache_min_uses 2 ; ## 引用次数超过2次就缓存
  3. open_file_cache_valid 60 ; ## 检查缓存有效性的时间间隔
  4. #####
  5. sendfile on ; ## 使用sendfile,可用将文件系统缓存中的文件直接发送到socket缓冲区
  6. sendfile_max_chunk 1024k ; ## 限制单次发送的文件量,避免大文件发送时阻塞进程
  7. directio 10m ; ## 针对大文件使用直接I/O,在内存不足的情况用途很大
  8. aio threads ; ## 当directio效果不明显时,可用启用aio和多线程任务卸载功能

5.3.2. 文件系统缓存

在不跳过文件系统缓存的情况下,系统内存中的cache会缓存大量的文件页和目录项,这种场景下配合sendfile也能降低磁盘I/O操作。

5.4. 请求和响应配置

5.4.1. 请求配置

  1. client_header_buffer_size 1k ; ## 请求头的缓冲区大小,一般无需调整。
  2. large_client_header_buffers 4 8k ; ## 超大请求头,一般无需调整。注意414和400返回码可能是请求头字段过大
  3. client_header_timeout 60s ; ## 请求头读取超时时间,超时返回408
  4. client_body_buffer_size 8k ; ## 默认是两个内存页大小(4k*2)
  5. client_max_body_size 1m ; ## 最大请求体大小,在上传服务器上,这个值会设置的非常大
  6. client_body_temp_path path 1 2 ; ## 对应较大请求体临时存放位置,一般用于应对上传服务器
  7. client_body_timeout 60s ; ## 两次读取请求体之间的最大时间间隔,超时返回408

5.4.2. 代理配置

  1. proxy_buffering on ; ## 开启对后端服务器响应的缓存,默认开启
  2. proxy_buffer_size 4k ; ## 缓存后端服务器响应的第一部分内容,一般就是响应头,此设置一般不需要调整。
  3. proxy_buffers 8 4k ; ## 单个连接读取后端服务器响应的缓冲区大小,超出则放入临时文件中。大文件比较大的情况下,可增加缓冲区大小
  4. proxy_max_temp_file_size 1024m ; ## 存储响应的临时文件总大小
  5. proxy_temp_file_write_size 8k ; ## 单个请求能写入临时文件中的大小
  6. proxy_busy_buffers_size 8k ; ## 当未发送的响应超过该值,则发送给响应给客户端,直到未发送的响应小于该值
  7. proxy_connect_timeout 30s ; ## 与后端服务器建立连接的超时时间
  8. proxy_read_timeout 30s ; ## 同一个请求,从后端服务器两次连续读取响应最大间隔时间
  9. proxy_send_timeout 30s ; ## 同一个请求,两次成功发送请求给后端服务器的间隔时间
  10. #### 以下在upstream模块配置
  11. keepalive 32 ; ## 每个工作进程与后端服务器保持的空闲连接数,不应该设置太大,避免影响后端服务器处理新的连接
  12. keepalive_timeout 60s ; ## 与后端服务器最长空闲连接时间
  13. keepalive_requests 100 ; ## 与后端服务器之间单个连接的完成的最大请求次数
  14. ### 以下针对健康检查配置,在upstream模块配置
  15. check interval=3000 fall=2 rise=3 timeout=1000 default_down=true type=http ;
  16. check_http_send "HEAD /check.html HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: keep-alive\r\n\r\n" ;
  17. check_http_expect_alive http_2xx http_3xx ;
  18. ## interval: 检查间隔(ms),此设置是上次检查失败或服务器异常情况下,下次检查的间隔。如果服务器正常则间隔为1min
  19. ## fall: 连续失败两次认为异常; rise: 连续成功两次认为正常; timeout: 请求超时时间(ms);
  20. ## default_down: 后端服务器初始状态,设置为true,表示后端服务器初始是异常的,通过检查后才认为正常; type: 检查方式
  21. ## check_http_send: http检查的方式,一般以head方式检查
  22. ## check_http_expect_alive: 认为后端服务器返回的正常状态码
  23. ## 这种健康检查方式在版本升级时非常有用,升级前移除check.html,升级完毕后恢复check.html

5.4.3. 响应配置

  1. send_timeout 60 ; ## 一个响应中,两次成功发送响应的最大时间间隔
  2. limit_rate 4096k ; ## 针对单个响应每秒中的限速,在大文件下载场景中比较有用

5.4.4. 流控

为了避免出现浪涌和攻击,可用使用流控方式来限制连接和请求。

  1. ## 针对连接的限制,不同http协议版本,同一个连接能完成的请求数量不一样,超出返回503
  2. limit_conn_zone $binary_remote_addr zone=addr:10m ; ## 1m大约能存储1.6万的地址池
  3. limit_conn addr 100 ; ## 限制单个客户端最大活跃连接数
  4. ## 针对请求的限制,超出返回503
  5. limit_req_zone $binary_remote_addr zone=limit_addr:10m rate=100r/s ; ## 系统将1s切成时间片来计算
  6. limit_req zone=limit_addr burst=100 nodelay; ## 延迟响应的请求数

5.4.5. HTTPS 服务器配置

SSL会话一般建议尽可能早的卸载掉,之后和后端服务器直接通过HTTP进行交互。SSL会话的成本较高,一个SSL会话尽可能完成更多的请求。

  1. keepalive_timeout 100s ; ## 长链接维持的时间
  2. keepalive_requests 200 ; ## 单个连接完成请求次数
  3. ssl_session_cache shared:SSL:30m ; ## 所有worker共享的会话缓存,1m大约能存4000会话
  4. ssl_session_timeout 10m ; ## SSL会话维持时间

5.4.6. 其它

  1. server_tokens off ; ## 不显示nginx版本号
  2. ## DNS 服务器配置
  3. resolver 223.5.5.5 ; ## dns服务器
  4. resolver_timeout 30s ; ## DNS解析超时时间
  5. ## 日志配置,合理配置日志切割脚本
  6. error_log logs/error.log error ; ## 适当提高error日志级别,减少磁盘IO
  7. log_format access '$time_local|$http_x_real_ip|$http_x_forwarded_for|$remote_addr|$upstream_addr|'
  8. '$request_method|$server_protocol|$host|$request_uri|$http_referer|$http_user_agent|'
  9. '$proxy_host|$status' ; ## 合理设置日志格式,时间格式可以修改源码
  10. access_log logs/access.log access buffer=128k flush=5s ; ## 当日志量较大时,使用日志缓冲区
  11. access_log off ; ## 针对部分请求,如健康检查、部分静态资源(css,js等)选择不记录日志