Nginx是现在最流行的Web服务器和反向代理服务器,很多网站都在用。Nginx性能非常高,能支持高并发占用资源少,但是很多人对Nginx的配置只是停留在表面,会简单的虚拟主机配置,但是对高性能配置、反向代理、负载均衡、缓存、安全加固等等了解不深,导致Nginx的性能没有发挥到极致。

我用Nginx很多年了,配置过很多高并发的网站,踩了很多坑也总结了很多经验,今天就来分享一下Nginx高性能配置的实战经验。

一、Nginx基础优化

首先我们来看看Nginx的一些基础优化配置,这些配置能大大提升Nginx的性能和并发能力。

1. worker_processes

worker_processes指定Nginx的worker进程数,一般设置为CPU核心数或者CPU核心数的2倍,比如服务器有4核CPU就设置为4或者8,这样能充分利用CPU多核的性能。

worker_processes auto;

设置为auto,Nginx会自动根据CPU核心数来设置worker进程数,很方便,推荐这样设置。

2. worker_connections

worker_connections指定每个worker进程能同时处理的最大连接数,默认是1024,对于高并发网站来说太小了,需要调大,比如设置为10240或者更大。但是也不能太大,要根据服务器的内存和性能来调整。

events {
    worker_connections 10240;
    use epoll;
    multi_accept on;
}

同时要设置use epoll,使用epoll事件模型,这是Linux下性能最好的事件模型,能大大提升并发处理能力。还要设置multi_accept on,让worker进程一次能接受多个新连接,提高效率。

注意Nginx的最大并发数 = workerprocesses * workerconnections,所以要根据服务器的性能和预期的并发数来合理设置这两个参数。

3. sendfile和tcp_nopush

sendfile开启高效文件传输模式,能大大提高静态文件的传输性能。tcp_nopush和sendfile一起开启,能减少网络包的数量,提高传输效率。

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
}

tcp_nodelay开启禁用Nagle算法,减少网络延迟,提高响应速度,对于动态请求很有好处。

4. keepalive_timeout

keepalive_timeout设置长连接的超时时间,长连接能减少TCP三次握手和四次挥手的开销,提高性能。但是也不能太长,不然会占用太多连接资源,一般设置为65秒左右比较合适。

http {
    keepalive_timeout 65;
    keepalive_requests 1000;
}

keepalive_requests设置一个长连接最多能处理的请求数,超过这个数就会关闭连接,默认是100,对于高并发网站可以调大一些,比如1000,减少连接重建的开销。

5. 客户端缓冲区设置

合理设置客户端请求的缓冲区大小,能提高Nginx处理请求的效率,也能避免一些攻击。

http {
    client_body_buffer_size 128k;
    client_max_body_size 20m;
    client_header_buffer_size 4k;
    large_client_header_buffers 4 32k;
}

clientmaxbody_size设置客户端请求体的最大大小,比如上传文件的大小,根据自己的需求设置,比如20m就是最大能上传20MB的文件。

6. 隐藏Nginx版本号

默认Nginx会在响应头和错误页显示版本号,这会让攻击者知道Nginx的版本,从而利用对应版本的漏洞进行攻击,所以建议隐藏版本号提高安全性。

http {
    server_tokens off;
}

设置server_tokens off就能隐藏Nginx的版本号,只显示nginx不显示具体版本,提高安全性。

二、Gzip压缩

开启Gzip压缩能大大减少传输的数据量,提高网站的加载速度,节省带宽,特别是对于文本类型的文件比如HTML、CSS、JS、XML、JSON等等,压缩效果非常好,能压缩60%-80%。

http {
    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_vary on;
    gzip_proxied any;
}
  • gzip on:开启Gzip压缩。
  • gzipminlength:设置最小压缩大小,小于这个大小的文件不压缩,因为太小的文件压缩效果不好反而浪费CPU,一般设置为1k或者10k。
  • gzipcomplevel:压缩级别1-9,数字越大压缩率越高但是越消耗CPU,一般设置为6比较合适,平衡压缩率和CPU消耗。
  • gzip_types:指定需要压缩的文件类型,要把文本类型的都加上,图片视频等二进制文件不需要压缩,因为已经是压缩格式了再压缩效果不好还浪费CPU。
  • gzip_vary on:添加Vary: Accept-Encoding响应头,让代理服务器能正确识别压缩和非压缩的版本。
  • gzip_proxied any:允许对代理请求也进行压缩。

开启Gzip压缩之后网站的加载速度会有明显的提升,特别是对于带宽小的服务器效果更明显。

三、静态资源缓存

对于静态资源比如图片、CSS、JS、字体等等,这些文件更新不频繁,可以设置浏览器缓存,让浏览器缓存这些文件,下次访问就直接从浏览器缓存读取,不用再请求服务器,大大提高网站的加载速度,也减少服务器的压力和带宽消耗。

server {
    # 图片缓存
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
    
    # CSS JS缓存
    location ~* \.(css|js)$ {
        expires 7d;
        add_header Cache-Control "public, no-transform";
    }
    
    # 字体缓存
    location ~* \.(eot|ttf|woff|woff2|otf)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
}
  • expires:设置缓存过期时间,比如30d就是缓存30天,7d就是缓存7天,根据文件更新频率设置,更新不频繁的文件可以设置长一些,更新频繁的文件设置短一些。
  • Cache-Control:设置缓存控制指令,public表示能被任何缓存缓存,包括浏览器和代理服务器,no-transform表示代理服务器不能修改文件内容。

注意HTML文件不要设置太长的缓存,因为HTML更新可能比较频繁,设置太长的缓存会导致用户看不到最新的内容,HTML可以设置比较短的缓存或者不缓存。

还有要注意缓存的文件更新的问题,如果文件内容更新了但是文件名没变,浏览器会继续用缓存的旧文件看不到最新的内容。所以更新静态文件的时候最好给文件名加版本号或者哈希值,比如style.v2.css、style.abc123.css,这样文件更新了文件名也变了,浏览器就会重新请求新文件不会用旧缓存。

四、反向代理配置

Nginx最常用的功能之一就是反向代理,把请求转发到后端的应用服务器比如PHP-FPM、Tomcat、Node.js等等。Nginx处理静态请求和反向代理的性能非常高,能大大提高网站的并发能力和稳定性。

下面是一个反向代理到PHP-FPM的配置例子:

server {
    listen 80;
    server_name example.com;
    root /var/www/html;
    index index.php index.html;
    
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        
        # 反向代理超时设置
        fastcgi_connect_timeout 60;
        fastcgi_send_timeout 60;
        fastcgi_read_timeout 60;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 128k;
        fastcgi_busy_buffers_size 256k;
    }
}
  • fastcgi_pass:指定PHP-FPM的地址和端口,PHP-FPM默认监听9000端口。
  • fastcgiparam SCRIPTFILENAME:指定脚本文件路径,这个很重要必须正确设置,不然PHP会找不到文件。
  • include fastcgi_params:包含默认的FastCGI参数。
  • fastcgiconnecttimeout:连接PHP-FPM的超时时间。
  • fastcgisendtimeout:发送请求到PHP-FPM的超时时间。
  • fastcgireadtimeout:读取PHP-FPM响应的超时时间,这个要根据PHP脚本的执行时间设置,比如有些脚本执行时间长就要设置长一些不然会超时。
  • fastcgibuffersize、fastcgibuffers、fastcgibusybufferssize:设置缓冲区大小,合理设置能提高反向代理的性能,减少磁盘IO。

如果是反向代理到其他的应用服务器比如Tomcat、Node.js,用proxypass而不是fastcgipass,配置类似:

location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    
    proxy_connect_timeout 60;
    proxy_send_timeout 60;
    proxy_read_timeout 60;
    proxy_buffer_size 128k;
    proxy_buffers 4 128k;
    proxy_busy_buffers_size 256k;
}
  • proxy_pass:指定后端应用服务器的地址。
  • proxysetheader:设置转发给后端的请求头,比如Host、真实IP等等,让后端能获取到正确的信息。
  • 其他超时和缓冲区设置和FastCGI类似。

五、负载均衡配置

当网站访问量大了,一台应用服务器扛不住了,就需要多台应用服务器做负载均衡,把请求分发到多台服务器上,提高并发能力和可用性。Nginx也能很方便地配置负载均衡。

http {
    upstream backend {
        server 192.168.1.101:9000 weight=1 max_fails=2 fail_timeout=30s;
        server 192.168.1.102:9000 weight=1 max_fails=2 fail_timeout=30s;
        server 192.168.1.103:9000 weight=2 max_fails=2 fail_timeout=30s;
        # ip_hash;
        # least_conn;
    }
    
    server {
        location ~ \.php$ {
            fastcgi_pass backend;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
    }
}
  • upstream:定义一个后端服务器组,名字叫backend,里面列出所有的后端服务器地址和端口。
  • weight:权重,权重越高分配到的请求越多,比如第三台服务器性能好就设置weight=2分配两倍的请求。
  • max_fails:最大失败次数,超过这个次数就认为这台服务器挂了不再转发请求给它。
  • failtimeout:失败超时时间,在这个时间内失败maxfails次就认为服务器挂了暂停转发给它,过了这个时间再尝试转发。
  • iphash:根据客户端IP的哈希来分配请求,同一个IP的请求会转发到同一台后端服务器,这样能解决session共享的问题,但是也可能导致负载不均衡,一般不推荐用,建议用Redis等做session共享而不是依赖iphash。
  • least_conn:把请求转发给当前连接数最少的后端服务器,能让负载更均衡,适合请求处理时间差异大的场景。

默认Nginx的负载均衡算法是轮询,按顺序依次把请求分发到各台服务器,结合weight权重,这是最常用的算法,大部分场景都适用。

配置负载均衡之后Nginx会自动把请求分发到多台后端服务器上,如果某台服务器挂了Nginx会自动把它剔除不再转发请求给它,等它恢复了再自动加回来,实现高可用,非常方便。

六、Nginx安全加固

最后我们来看看Nginx的一些安全加固配置,能提高网站的安全性,防止一些常见的攻击。

1. 禁止访问敏感文件

对于一些敏感文件比如.env配置文件、.git版本控制目录等等,要禁止访问,防止敏感信息泄露。

server {
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
    
    location ~ ~$ {
        deny all;
        access_log off;
        log_not_found off;
    }
}

这样所有以.开头的文件和目录比如.env、.git、.htaccess等等都禁止访问,返回403,防止敏感信息泄露。

2. 禁止指定请求方法

如果网站只需要GET和POST请求,可以禁止其他的请求方法比如DELETE、PUT、TRACE等等,减少攻击面。

server {
    if ($request_method !~ ^(GET|POST)$ ) {
        return 405;
    }
}

这样只有GET和POST请求能访问,其他请求方法都返回405 Method Not Allowed。

3. 防止SQL注入和XSS

可以用Nginx的配置简单防止一些常见的SQL注入和XSS攻击,当然这只是辅助,根本还是要在代码层面做好防护。

server {
    if ($query_string ~* (union|select|insert|update|delete|drop|alter|create|exec|execute|script|javascript|alert|document|cookie)) {
        return 403;
    }
}

这样如果URL参数里包含这些常见的SQL注入和XSS关键词就返回403禁止访问,能挡住一些简单的攻击,但是不能完全依赖这个,代码层面还是要做好参数过滤和转义。

4. 限制请求频率

可以用Nginx的limit_req模块限制客户端的请求频率,防止CC攻击和暴力破解。

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
    
    server {
        location / {
            limit_req zone=one burst=20 nodelay;
        }
    }
}
  • limitreqzone:定义一个请求频率限制区域,按客户端IP限制,zone名字叫one,大小10m,速率10r/s就是每秒最多10个请求。
  • limit_req:在location里应用这个限制,burst=20表示允许突发20个请求,nodelay表示突发的请求不延迟立即处理,超过的才返回503。

这样能限制每个IP每秒最多10个请求,突发20个,能有效防止CC攻击和暴力破解。

5. 配置HTTPS

现在HTTPS已经是标配了,特别是涉及登录支付等等敏感操作的网站必须用HTTPS。Nginx配置HTTPS也很简单,需要先申请SSL证书然后配置就行。

server {
    listen 443 ssl;
    server_name example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    
    # 其他配置...
}

# HTTP跳转到HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}
  • sslcertificate、sslcertificate_key:指定证书和私钥文件路径。
  • ssl_protocols:指定支持的TLS版本,建议只支持TLSv1.2和TLSv1.3,禁用旧的不安全的SSLv2、SSLv3、TLSv1.0、TLSv1.1。
  • ssl_ciphers:指定加密套件,禁用不安全的加密套件。
  • sslsessioncache、sslsessiontimeout:配置SSL会话缓存,提高HTTPS的性能,减少SSL握手的开销。
  • 把HTTP请求301跳转到HTTPS,让所有请求都走HTTPS。

配置HTTPS之后网站的安全性会大大提高,数据传输是加密的防止被窃听和篡改,也能提高网站在搜索引擎的排名。

七、写在最后

Nginx高性能配置实战:从反向代理到负载均衡。

Nginx是一款非常优秀的Web服务器和反向代理服务器,性能高配置灵活功能丰富,掌握了Nginx的高性能配置能大大提升网站的性能和稳定性,让网站又快又稳。

这篇文章分享了Nginx的基础优化、Gzip压缩、静态资源缓存、反向代理、负载均衡、安全加固等等配置和实战经验,希望能帮大家更好地配置和优化Nginx。

当然Nginx的功能还有很多,比如流媒体、缓存、限流、ACL等等,这里就不一一介绍了,大家可以根据自己的需求去学习和使用。

最后用一句话结尾:

"Nginx是Web服务器的瑞士军刀,配置好了能让你的网站飞起来。"

祝大家的Nginx都配置得又快又稳,网站访问飞快!