Nginx 性能优化配置

threcial 发布于 2 天前 22 次阅读


Nginx 默认参数偏保守,适合最小硬件环境。真实业务里通常会调整

高并发优化:worker 和连接数

worker_processes auto;

events {
    worker_connections 4096;
}

worker_processes 通常按 CPU 核心数设置,直接 auto 就可以

worker_connections 是每个 worker 的最大连接数,可以从 4096 起步,并且习惯上取 2 的指数。如果 Nginx 是反向代理,一个客户端请求可能同时占用客户端连接和后端连接,所以理论连接数不能简单等于客户端数量

长连接优化:keepalive

HTTP 基于 TCP,每次短连接都要三次握手、四次挥手。keepalive 的作用就是复用连接

keepalive_timeout 15;
keepalive_requests 8192;

默认是 65 秒,建议改到 15 秒左右,太长会让空闲连接长期占用 fd、worker_connections 和内存

keepalive_requests 表示一个长连接最多处理多少个请求,达到后关闭

数据传输优化:sendfile 和 gzip

静态文件传输建议开启:

sendfile on;
这是零拷贝方向的优化,可以减少用户态和内核态之间的数据拷贝

gzip 用于文本资源压缩:

gzip on;
gzip_proxied any;
gzip_min_length 10k;
gzip_comp_level 6;
gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/javascript application/json;

压缩能节省带宽,让用户更快拿到文本内容。但不要压缩图片、视频、音频、压缩包,这些本身已经压缩过,再压缩收益很小,还消耗 CPU

隐藏版本号:

server_tokens off;

客户端缓存

音视频、图片这类资源无法通过 gzip 得到明显收益,更适合让浏览器缓存:

location ~* \.(png|gif|jpg|mp3|mp4|wav|avi)$ {
    expires 1h;        可以写30m 1h 1d 表示30分钟、一小时、一天
    root html;
}

缓存时间要按业务来,频繁变化的资源不要长缓存,带 hash 或版本号的静态资源可以缓存更久

负载均衡:Nginx 作为七层分发器

单台服务器总会遇到瓶颈,也会有单点故障,所以需要在前面放分发器,也就是反向代理的实际应用

常见方式有

轮询

upstream web {
    server 192.168.0.120;
    server 192.168.0.121;
    server 192.168.0.122;
}

server {
    listen 80;

    location / {
        proxy_pass http://web;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

默认按请求顺序轮询转发

权重

upstream web {
    server 192.168.0.120 weight=10;
    server 192.168.0.121 weight=3;
    server 192.168.0.122;
}

没有写 weight 时默认是 1,权重越高,分到的请求越多

ip_hash

upstream web {
    ip_hash;
    server 192.168.0.120;
    server 192.168.0.121;
    server 192.168.0.122;
}

ip_hash 会基于客户端 IP 做哈希,让同一个用户尽量落到同一台后端。这个常用于保持 session 一致性

后端状态有:
down    不参与处理请求
backup  其他机器忙或不可用时才参与
weight  权重

Keepalived:解决分发器单点故障

后端业务服务器挂了,Nginx upstream 可以临时绕开,但如果前端分发器本身挂了,就需要高可用

这时就用到 Keepalived , Keepalived 基于 VRRP 协议,实现 VIP 漂移

比如一个 keepalived 结构:

Nginx-1  MASTER
Nginx-2  BACKUP
 VIP      192.168.31.33

用户访问 VIP,正常情况下 VIP 在 MASTER 上,MASTER 挂了,BACKUP 接管 VIP

Keepalived 默认通过 VRRP 多播发送通告。MASTER 定时告诉 BACKUP:我还活着。如果 BACKUP 一段时间收不到,就会参与选举并接管 VIP

云主机环境通常不支持这种二层 VIP 漂移,云厂商一般提供 SLB/负载均衡产品,所以云上直接用 SLB 更合适

MASTER 示例:

global_defs {
    router_id wb01
}                      当前机器的唯一标识

vrrp_script chk_nginx {
    script "/etc/keepalived/nginx_check.sh"
    interval 1
}                       定义一个脚本,每秒执行一次

vrrp_instance VI_1 {
    state MASTER                master
    interface ens33             本机网卡
    virtual_router_id 33        vip标识
    priority 150                优先级,数值越大越高
    advert_int 1           

    authentication {         
        auth_type PASS
        auth_pass 1111
    }                          验证方式

    track_script {
        chk_nginx              使用脚本
    }

    virtual_ipaddress {
        192.168.31.33/24 dev ens33 label ens33:3         
    }                            vip在本机的配置
}

BACKUP 示例:

global_defs {
    router_id wb02
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 33        与 master 一致
    priority 100                 比 master 低
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass 1111
    }

    virtual_ipaddress {
        192.168.31.33/24 dev ens33 label ens33:3      虚拟ip配置
    }
}

以下四个配置必须一致

virtual_router_id
authentication
virtual_ipaddress
advert_int

而以下三个一般不同

router_id          唯一
priority        MASTER 通常高于 BACKUP
interface        真实网卡

因为 Keepalived 只能保证主机存活而不能与 Nginx 产生联动,所以需要在 Master 上添加一个脚本来时刻检测 Nginx 的状态,当 Nginx 出现问题时就移交 Vip

#!/bin/bash
pidof nginx >/dev/null 2>&1
if [ $? -ne 0 ]; then
    sleep 1
fi
exit 0

裂脑问题

裂脑就是两台机器都认为自己是 MASTER,于是同时持有同一个 VIP,结果就是同一个 IP 在网络里对应两个 MAC,访问混乱

常见原因:

心跳链路问题
网卡故障
交换机故障
VRRP 报文被拦截
配置不一致

缓解方式:

增加冗余心跳链路
监控 VIP 是否同时存在
监控 BACKUP 是否在 MASTER 正常时错误持有 VIP

比如:在备节点上检查,如果能连通主节点 80 端口,并且备节点自己又持有 VIP,就报警,因为主节点 Web 服务正常时,备节点不应该接管 VIP。