Nginx调优总结

摘要

如果客户数据量,用户量,并发量巨大.
一台服务器肯定是无法支撑的. 
一来不安全系统不稳定,二来性能肯定是无法满足的
此时就需要有一个负载均衡的服务器.
如果并发量成千上万, 建议还是使用硬件的F5等做负载
如果并发量在几十到几百之间, 可以使用开源的Nginx进行
反向代理+负载均衡. 
但是需要注意, 能够使用和能够高性能的使用是两个维度的事情. 
需要进行大量的调优工作才可以

调优提纲

1. Nginx配置内容调优.
2. 系统内核参数调优.
3. 操作系统优化
4. 网络部分调优
5. 容器运行时调优

第一部分: Nginx配置内容调优

worker_processes 1; 
一般不大于操作系统的CPU个数,但是线程数量太多也不是好事情.
可以设置为auto 默认等于机器内的CPU数量.
worker_cpu_affinity auto;
可以实现CPU绑定到可用的内核.
这样性能会好一些. 

events {
    worker_connections 65535;
    use epoll;
    multi_accept on;
}
worker_connections  可以设置的比较大一点. 
Linux可以使用epoll 的IO模型性能比较好.

nginx配置情况

listen 80 backlog=1024;
可以修改nginx 源码里面的默认backlog数值.
Nginx能够支持多少并发量是由
min(somaxconn,backlog) 来决定的
不仅要修改 内核的参数还要修改 Nginx的参数

ulimit -HSn 65535
需要修改能够打开的文件数. 
可以修改 /etc/security/limits.conf 
使之永久生效.

部分tcp部分的设置

keepalive_timeout 180;
keepalive_requests 10000;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
Keep alive能减少浏览器重新连接的次数。
keepalive_timeout和keepalive_requests控制保持活动设置。
sendfile优化Nginx提供文件系统的静态文件服务的性能,一般能够说还想zero Copy的效果
tcp_nodelay允许Nginx使TCP发送多个缓冲区作为单独的数据包。
tcp_nopush通过激活TCP堆栈中的TCP_CORK选项来优化一次向下游发送的数据量。
TCP_CORK阻塞数据,直到分组到达MSS,这等于MTU减去IP报头的40或60字节。

部分配置文件

client_body_buffer_size      128k;
client_max_body_size         200m;
client_header_buffer_size    1k;
large_client_header_buffers  4 4k;
output_buffers               1 32k;
postpone_output              1460;

调整缓冲区大小可能是有利的。 如果缓冲区大小太低,
那么Nginx将写入一个临时文件。 这将导致过多的磁盘I/O。
可能会出现一个 proxy_temp 目录,需要设置目录的可读权限.

client_body_buffer_size: 处理客户端缓冲区大小。 
   大多数客户端缓冲区都来自POST方法表单提交。 128k通常是此设置的不错选择。
client_max_body_size: 设置最大body缓冲区大小。 
   如果请求中的大小超过配置的值,则会将413(请求实体过大)错误返回给客户端。 
   不过浏览器无法正确显示413错误。 将大小设置为0将禁用对客户机请求正文大小的检查。
client_header_buffer_size: 处理客户端头大小。 默认情况下,1k通常是一个合理的选择。
large_client_header_buffers: 设置客户端头的缓冲区的最大数量和大小。 4个报头与4k缓冲区应该足够了。
postpone_output: 设置用于从磁盘读取响应的缓冲区的数量和大小。 
   如果可能,客户端数据的传输将被推迟,直到Nginx至少具有要发送的数据的字节数的集合大小。 零值禁止推迟数据传输。

部分配置文件

client_header_timeout  3m;
client_body_timeout    3m;
send_timeout           3m;

超时设置还可以大幅提高性能。
client_body_timeout  : 指令设置服务器等待客户端完成发送body的最大时间。
client_header_timeout: 指令设置服务器等待客户端完成发送header的最大时间。
send_timeout         : 指定对客户端的响应超时。 
此超时不适用于整个传输,而是仅应用于两个后续的客户端读取操作之间。 
因此,如果客户端没有读取任何数据这段时间,那么Nginx关闭连接。

部分配置文件

gzip on;
gzip_min_length 1000;
gzip_types: text/html application/x-javascript text/css \
application/javascript text/javascript text/plain text/xml \
application/json application/vnd.ms-fontobject application/x-font-opentype \
application/x-font-truetype application/x-font-ttf application/xml font/eot \
font/opentype font/otf image/svg+xml image/vnd.microsoft.icon;
gzip_disable "MSIE [1-6]\.";

对于纯文本的内容,Nginx可以使用gzip压缩将这些资源返回给客户端。
现代的网络浏览器都支持gzip压缩的内容,这将减少网络传输的字节数。
下面的列表是可压缩内容类型的“安全”列表; 但是,您只需要启用您在Web应用程序中使用的内容类型。

基于浏览器的设置

if ($http_user_agent ~ Firefox) {
rewrite ^(.*)/firefox/
1 break;}

if ($http_user_agent ~ MSIE) {
rewrite ^(.*)/msie/
1 break;}

if ($http_user_agent ~ Chrome) {
rewrite ^(.*)/chrome/
1 break;}

防盗链设置

server_tokens off;
# 关于nginx的版本, 避免体现安全问题

location ~* \.(jpg|gif|jpeg|png)$ {
valid_referers none blocked www.jinanxiaolaohu.com;
if ($invalid_referer) {
rewrite ^/ http://www.jinaniaolaohu.com/403.html;
  }
}
# 防盗链

if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
    return 403;}
# 防止爬虫

部分文件实现断点续传

# 注意可以关闭部分日志来提高性能. 

  location ~ ^/(img/|js/|css/|upload/|font/|fonts/|res/|video) {
    add_header Access-Control-Allow-Origin *;
    add_header Accept-Ranges bytes;
    root /var/www/...;
    access_log off;
    expires 30d;

return和rewrite

方法1
if ( $scheme = http ) {
    return 301 https://$host$request_uri;}
方法2
if ( $server_port = 80 ) {
    return 301 https://$host$request_uri;}
方法3
server {
    listen 80;
    server_name www.abc.com;
    return 301 https://$server_name$request_uri; }     
方法4
if ( $host = "www.abc.com" ) {
    rewrite ^/(.*)$ https://www.abc.com permanent;}

return和rewrite

rewrite: 能够实现复杂的正则表达式规则.
return: 仅能够进行简单的路径转发

但是rewrite 因为有一些 正则算法, 可能会导致性能损失.
如果使用retrun 的话性能要比rewrite要好一些. 

性能就是如此, 都是积小成多集腋成裘的过程. 
虽然一点点改进可能看起来很细小, 但是如果在大并发情况下
会有很大的改善.

第二部分: 系统内核参数调优

net.ipv4.tcp_max_tw_buckets = 6000
对于tcp连接,服务端和客户端通信完后状态变为timewait,
假如某台服务器非常忙,连接数特别多的话,那么这个timewait数量就会越来越大。

net.ipv4.tcp_tw_reuse = 1
开启重用。该参数设置为1,将timewait状态的连接重新用于新的TCP连接

net.ipv4.tcp_syncookies = 1
设置为1,是开启SYN Cookies,开启后可以避免发生syn flood攻击。

net.ipv4.tcp_max_syn_backlog = 262144
该参数定义系统能接受的最大半连接状态的tcp连接数。
客户端向服务端发送了syn包,服务端收到后,会记录一下,该参数决定最多能记录几个这样的连接。

net.ipv4.tcp_syn_retries = 2
该参数适用于客户端,它定义发起syn的最大重试次数,默认为6,建议改为2。

net.ipv4.tcp_synack_retries = 2
该参数适用于服务端,它定义发起syn+ack的最大重试次数,
默认为5,建议改为2,可以适当预防syn flood攻击。

系统内核参数调优配置

net.ipv4.ip_local_port_range
这个参数定义随机端口的范围。默认为32768 60999,建议调整为1025 6099

net.ipv4.tcp_fin_timeout = 6
内核的通常值是180 秒,你可以按这个设置,但要记住的是,即使你的机器是一个轻载的WEB 服务器,
也有因为大量的死套接字而内存溢出的风险,FIN- WAIT-2 的危险性比FIN-WAIT-1 要小,
因为它最多只能吃掉1.5K 内存,但是它们的生存期长些。建议调整为6。

net.ipv4.tcp_keepalive_time = 600
服务端为了确认客户端是否断网,就需要每隔一段时间去发一个探测包去确认一下看看对方是否在线。
这个时间就由该参数决定。它的默认值为7200秒,建议设置为600秒

net.ipv4.tcp_keepalive_intvl = 15
该参数和上面的参数是一起的,服务端在规定时间内发起了探测,查看客户端是否在线,
如果客户端并没有确认,此时服务端还不能认定为对方不在线,而是要尝试多次。
该参数定义重新发送探测的时间,即第一次发现对方有问题后,过多久再次发起探测。默认值为75秒,可以改为15秒。

net.ipv4.tcp_keepalive_probes = 3
该参数定义发起探测的包的数量。默认为9,建议设置3。

系统内核参数调优配置

net.core.somaxconn = 16384
web应用中listen函数的backlog默认会给我们内核参数的net.core.somaxconn限制到128,
而nginx定义的NGX_LISTEN_BACKLOG默认为511

net.core.netdev_max_backlog = 16384
每个网络接口接收数据包的速率比内核处理这些包的速率快时,
允许送到队列的数据包的最大数目。默认值是1024,对重负载服务器而言,该值需要调高一点。
注意: 这个参数是进入网卡还没进入CPU的. 

net.ipv4.tcp_max_orphans = 32768
系统所能处理不属于任何进程的TCP sockets最大数量。
假如超过这个数量﹐那么不属于任何进程的连接会被立即reset,并同时显示警告信息。
之所以要设定这个限制﹐纯粹为了抵御那些简单的 DoS 攻击﹐千万不要依赖这个或是人为的降低这个限制。
如果内存大更应该增加这个值。系统默认是8092,可以修改为32768。

net.ipv4.tcp_retries2 = 5
在丢弃激活(已建立通讯状况)的TCP连接之前﹐需要进行多少次重试。默认值为15,
根据RTO的值来决定,相当于13-30分钟(RFC1122规定,必须大于100秒).
(这个值根据目前的网络设置,可以适当地改小,可以修改为5)

部分内核参数

net.ipv4.tcp_rmem = 10240 87380 12582912 
这个参数定义了TCP接受缓存(用于TCP接受滑动窗口)的最小值、默认值、最大值。

net.ipv4.tcp_wmem = 10240 87380 12582912
这个参数定义了TCP发送缓存(用于TCP发送滑动窗口)的最小值、默认值、最大值。

net.core.rmem_default = 6291456
这个参数表示内核套接字接受缓存区默认的大小。

net.core.wmem_default = 6291456
这个参数表示内核套接字发送缓存区默认的大小。

net.core.rmem_max = 12582912
这个参数表示内核套接字接受缓存区的最大大小。

net.core.wmem_max = 12582912
这个参数表示内核套接字发送缓存区的最大大小。

nf模块的参数配置

net.netfilter.nf_conntrack_tcp_timeout_established = 1800
#以下可能需要加载ip_conntrack模块 modprobe ip_conntrack ,
有文档说防火墙开启情况下此模块失效
#縮短established的超時時間

net.netfilter.nf_conntrack_max = 1048576
net.nf_conntrack_max = 1048576
#CONNTRACK_MAX 允许的最大跟踪连接条目,是在内核内存中netfilter可以同时处理的“任务”
(连接跟踪条目)

net.netfilter.nf_conntrack_tcp_timeout_close_wait = 30
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 60
#可以根据情况适当修改TCP的各个阶段的超市时间设置.

判断部分网络的参数

可以通过如下命令查看服务器建立的连接情况
netstat -an|awk '/^tcp/{++S[$NF]}END{for(a in S) print a,S[a]}'
或者使用这个命令:
ss -a|grep '^tcp'|awk '{print $2}'|sort|uniq -c|sort -rn

可以根据出现的连接信息进行判断是否需要进行优化

部分邮件参数建议

net.ipv4.tcp_fin_timeout = 6
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_max_tw_buckets = 8000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 30000
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
net.ipv4.ip_local_port_range = 1025 61000
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_keepalive_probes = 3
net.core.somaxconn = 16384
net.core.netdev_max_backlog = 16384
net.ipv4.tcp_max_orphans = 32768
net.ipv4.tcp_retries2 = 5
net.ipv4.tcp_rmem = 10240 87380 12582912 
net.ipv4.tcp_wmem = 10240 87380 12582912
net.core.rmem_default = 6291456
net.core.wmem_default = 6291456
net.core.rmem_max = 12582912
net.core.wmem_max = 12582912
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 30
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 60
net.netfilter.nf_conntrack_max = 1048576
net.nf_conntrack_max = 1048576
net.netfilter.nf_conntrack_tcp_timeout_established = 1800

第三部分: 操作系统优化

1. 操作系统需要专用,尽量不要承载其他业务.
2. 操作系统需要设置电源模式为高性能.避免降频时出现性能下降.
3. 日志较多时建议选用单独的盘来存在nginx的日志.避免磁盘写入速度影响性能.
4. 前后端分离时, 增加高性能的存储前端文件作为缓存.
5. RAID卡可以适当提高缓存使用, nginx服务器应该是高读少写的场景.

日志部分归档处理

source /etc/profile        #加载系统环境变量
source ~/.bash_profile    #加载用户环境变量
set -o nounset             #引用未初始化变量时退出
set -o errexit            #执行shell命令遇到错误时退出

PID="/usr/local/nginx/logs/nginx.pid"    #pid目录
NGINX="/usr/local/nginx/sbin/nginx"
YESTERDAY=$(date -d "yesterday" +%Y-%m-%d)    #昨天日期
LOGS_PATH="/data/nginx/logs"    #日志目录
server_names=("access_chaoneng")    #日志名
server_count=${#server_names[@]}

cut_logs(){
        local name=$1
        cd $LOGS_PATH
        /bin/mv -f ${name}.log  ${name}.${YESTERDAY}.log
        #三种方式,根据需求使用任意一种
        #service nginx reload
        #kill -USR1 $(cat $PID)
        $NGINX -s reload
        tar zcf ${name}.${YESTERDAY}.log.gz ${name}.${YESTERDAY}.log
        rm -rf ${name}.${YESTERDAY}.log
}

第四部分: 网络部分调优

1. 虚拟机网卡与驱动.
举例: ESXi的虚拟机有E1000和VNET3的多种网卡.
建议安装vmtools.并且选择高配置的万兆甚至更高的网卡进行业务处理.
2. 使用ping iperf3 或者是其他指令进行延迟和带宽验证.
避免反向代理和服务器之间出现异常. 
3. 物理服务器之间尽量使用光纤连接,虽然超六类RJ45线可以达到万兆
但是电口的效率不如光口.
4.交换机也可以进行一些响应的处理.提高效率.尽量专用.
5.尽量业务网络和管理控制网络可以分散开.
6.客户端和反向代理的服务端可以选用不通的网口,不同的网段.提高效率.

第五部分: 容器运行时调优

首先: 
使用docker0桥接网卡,不如直接 --net=host的方式执行效率高
如果是一个专用的Nginx服务区可以选择使用 --net=host的方式来执行.

其次:
如果必须使用桥接网络, 不能使用本地网络需要进行调优配置.
尽量不要对容器的限制太多, 尽量能够使用整个机器的资源. 

再次:
需要使用 --sysctl的方式来修改容器的配置文件. 
主要修改点与内核修改部分类似.
需要注意. 虽然容器与宿主机共享内核,但是宿主机的修改可能无法影响容器运行时.
比如需要使用:
docker run -it --rm --sysctl net.core.somaxconn=65535 busybox \
cat /proc/sys/net/core/somaxconn

容器内参数验证

sysctl -w  net.core.somaxconn=65535
#验证参数修改是否有效
sysctl -a |grep somaxconn
# 执行容器进行验证
docker run -it --rm busybox /bin/sh
# 执行: cat /proc/sys/net/core/somaxconn
结果为: 128
docker run -it --net=host --rm busybox /bin/sh
# 执行: cat /proc/sys/net/core/somaxconn
结果为: 65535
# 使用--net=host 会继承操作系统内的参数.
# 使用brigde 模式不会继承.

K8S内修改系统内核参数

      initContainers:
      - command:
        - sysctl
        - -w
        - net.ipv4.tcp_keepalive_time=180
        image: busybox:1.27
        name: init-sysctl
        securityContext:
          privileged: true

K8S内修改系统内核参数

      initContainers:
      - command:
        - /bin/sh
        - -c
        - |
          ulimit -n 65536
          mount -o remount rw /sys
          echo never > /sys/kernel/mm/transparent_hugepage/enabled
          mount -o remount rw /proc/sys
          echo 2000 > /proc/sys/net/core/somaxconn
          echo 1 > /proc/sys/vm/overcommit_memory
        image: registry.cn-beijing.aliyuncs.com/acs/busybox:v1.29.2
        imagePullPolicy: IfNotPresent
        name: init-redis
        resources: {}
        securityContext:
          privileged: true
          procMount: Default
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值