在Web开发和运维中Web服务器的性能直接影响网站的访问速度和用户体验。Nginx作为目前最流行的高性能Web服务器和反向代理服务器凭借其高性能高并发低资源消耗等优点被广泛应用于各种Web项目,中。

但是默认的Nginx配置并不是最优的需要根据服务器配置和网站需求进行适当的优化才能发挥Nginx的最佳性能。今天就来分享一下Nginx高性能Web服务器的配置优化指南包括基础优化性能优化安全加固Gzip压缩缓存配置等希望能帮到大家。

1. Nginx简介

Nginx是一个高性能的HTTP和反向代理服务器也是一个IMAP/POP3/SMTP代理服务器。它由俄罗斯程序员Igor Sysoev开发首次发布于2004年。

Nginx的特点包括:

  • 高性能:采用事件驱动异步非阻塞模型能支持高并发连接单机能支持数万甚至数十万并发连接。
  • 低资源消耗:相比Apache,Nginx占用的内存和CPU资源更少同样的服务器配置能承载更多的访问。
  • 高可靠性:Nginx经过多年的发展和验证非常稳定可靠很多大型网站都在使用Nginx。
  • 丰富的功能:Nginx不仅是一个Web服务器还支持反向代理负载均衡缓存Gzip压缩SSL/TLS虚拟主机等丰富的功能。
  • 模块化设计:Nginx采用模块化设计功能都是通过模块实现的可以根据需求编译和加载不同的模块。

目前Nginx已经成为最流行的Web服务器之一很多大型网站比如百度淘宝京东腾讯等都在使用Nginx。

2. 基础优化

2.1 worker进程优化

Nginx采用多进程模型有一个master进程和多个worker进程。master进程负责管理和监控worker进程worker进程负责处理实际的请求。

worker进程的数量应该设置为CPU核心数这样每个worker进程都可以绑定一个CPU核心避免进程切换的开销提高性能。

# 设置worker进程数为CPU核心数
worker_processes auto;

# 绑定worker进程到CPU核心(可选)
worker_cpu_affinity auto;

worker_processes auto; 会自动根据CPU核心数设置worker进程数是最简单和推荐的设置。

2.2 worker连接数优化

每个worker进程能处理的最大连接数由,worker_connections,指令控制。默认值是512对于高并发网站来说太小了需要调大。

events {
    # 每个worker进程的最大连接数
    worker_connections 10240;
    
    # 启用高效的网络连接处理方法
    use epoll;
    
    # 允许同时接受多个新连接
    multi_accept on;
}

worker_connections 的值需要根据服务器内存和预期并发数来设置。一般来说每个连接占用大约2-4KB内存10240个连接大约占用20-40MB内存对于大多数服务器来说都没问题。

use epoll; 启用Linux下高效的epoll事件处理模型能大大提高网络IO性能。

multi_accept on; 允许worker进程一次接受多个新连接提高并发处理能力。

2.3 文件描述符优化

Linux系统默认的文件描述符限制比较小对于高并发网站来说可能不够需要调大。

# 全局最大文件描述符数
worker_rlimit_nofile 65535;

同时也需要修改Linux系统的文件描述符限制编辑,/etc/security/limits.conf,文件:

* soft nofile 65535
* hard nofile 65535

2.4 隐藏Nginx版本号

默认情况下Nginx会在HTTP响应头和错误页面中显示版本号这可能会被攻击者利用针对特定版本的漏洞进行攻击。建议隐藏版本号。

# 隐藏Nginx版本号
server_tokens off;

3. 性能优化

3.1 启用Gzip压缩

Gzip压缩能大大减小HTTP响应的大小减少带宽占用提高网站访问速度。

# 启用Gzip压缩
gzip on;

# 压缩级别(1-9,数字越大压缩率越高,但CPU占用也越高)
gzip_comp_level 6;

# 最小压缩文件大小(小于这个值的文件不压缩)
gzip_min_length 1k;

# 压缩的文件类型
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/xml image/svg+xml;

# 是否在响应头中添加Vary: Accept-Encoding
gzip_vary on;

# 是否对代理请求启用压缩
gzip_proxied any;

# 禁用IE6以下浏览器的Gzip压缩(IE6以下对Gzip支持不好)
gzip_disable "MSIE [1-6]\.";

gzipcomplevel 的值建议设置为5-6压缩率和CPU占用比较平衡。设置太高压缩率提升有限但是CPU占用会大大增加。

3.2 静态文件缓存

对于静态文件比如图片CSS,JS等变化不频繁可以设置较长的缓存时间减少服务器请求提高访问速度。

# 图片缓存
location ~* \.(jpg|jpeg|png|gif|ico|webp|svg)$ {
    expires 30d;
    add_header Cache-Control "public, no-transform";
}

# CSS和JS缓存
location ~* \.(css|js)$ {
    expires 7d;
    add_header Cache-Control "public, no-transform";
}

# 字体文件缓存
location ~* \.(woff|woff2|ttf|otf|eot)$ {
    expires 30d;
    add_header Cache-Control "public, no-transform";
}

expires 指令设置缓存过期时间浏览器会在过期时间内直接使用本地缓存不向服务器发送请求。

3.3 打开文件缓存

Nginx的,openfilecache,能缓存经常访问的文件的文件描述符和元信息减少文件IO操作提高性能。

# 打开文件缓存
open_file_cache max=65535 inactive=60s;

# 打开文件缓存的最小访问次数
open_file_cache_min_uses 2;

# 打开文件缓存的校验间隔
open_file_cache_valid 60s;

# 是否在打开文件缓存中记录错误
open_file_cache_errors on;

openfilecache max=65535 inactive=60s; 表示最多缓存65535个文件60秒内没有被访问的文件会被清除。

3.4 发送文件优化

Nginx的,sendfile,指令能启用Linux的sendfile系统调用直接将文件从磁盘发送到网络接口不需要经过用户空间大大提高静态文件的发送效率。

# 启用sendfile
sendfile on;

# 启用TCP_NOPUSH(在sendfile启用时有效,减少网络包数量)
tcp_nopush on;

# 启用TCP_NODELAY(禁用Nagle算法,减少延迟)
tcp_nodelay on;

sendfile on; 是提高静态文件发送效率的重要设置建议启用。

3.5 客户端超时优化

合理设置客户端超时时间能避免慢连接占用过多资源提高服务器并发处理能力。

# 客户端连接超时时间
client_header_timeout 10s;
client_body_timeout 10s;

# 发送响应超时时间
send_timeout 10s;

# 保持连接超时时间
keepalive_timeout 65s;

# 保持连接的最大请求数
keepalive_requests 100;

keepalive_timeout 设置HTTP长连接的超时时间合理的长连接能减少TCP连接建立和断开的开销提高性能。

4. 安全加固

4.1 禁止访问敏感文件

对于一些敏感文件比如配置文件日志文件备份文件等应该禁止外部访问防止敏感信息泄露。

# 禁止访问隐藏文件
location ~ /\. {
    deny all;
    access_log off;
    log_not_found off;
}

# 禁止访问备份文件
location ~ ~$ {
    deny all;
    access_log off;
    log_not_found off;
}

# 禁止访问配置文件
location ~ \.(ini|conf|env|log|sql|bak|old)$ {
    deny all;
    access_log off;
    log_not_found off;
}

4.2 限制请求大小

限制客户端请求体的大小能防止用户上传过大的文件导致服务器资源耗尽。

# 限制请求体大小
client_max_body_size 10m;

根据网站需求设置合适的值比如普通博客网站设置为10m就足够了如果需要上传大文件可以设置更,大。

4.3 防止DDoS攻击

通过限制单个IP的连接数和请求速率能一定程度上防止DDoS攻击。

# 定义限流区域
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;

server {
    # 限制单个IP的并发连接数
    limit_conn conn_limit 20;
    
    # 限制单个IP的请求速率
    limit_req zone=req_limit burst=20 nodelay;
    
    # 限流后的状态码
    limit_req_status 429;
    limit_conn_status 429;
}

limitconnzone 限制单个IP的并发连接数,limitreqzone 限制单个IP的请求速率。合理设置这些值能一定程度上防止DDoS攻击但是对于大规模DDoS攻击还是需要专业的DDoS防护服务。

4.4 禁用不安全的HTTP方法

对于大多数网站来说只需要GET和POST方法其他方法比如PUT,DELETE,TRACE,OPTIONS等都不需要可以禁用防止被利用进行攻击。

# 只允许GET和POST方法
if ($request_method !~ ^(GET|POST)$) {
    return 405;
}

5. PHP-FPM优化

如果Nginx配合PHP-FPM使用还需要对PHP-FPM进行优化。

5.1 进程管理优化

PHP-FPM的进程管理方式有static,dynamic,ondemand三种。对于高并发网站建议使用static模式固定进程数避免进程频繁创建和销毁的开销。

编辑,php-fpm.conf,或,www.conf,文件:

; 进程管理方式
pm = static

; 最大子进程数
pm.max_children = 50

; 启动时的进程数(static模式下等于max_children)
pm.start_servers = 50

; 最小空闲进程数
pm.min_spare_servers = 20

; 最大空闲进程数
pm.max_spare_servers = 50

; 每个进程处理的最大请求数(防止内存泄漏)
pm.max_requests = 500

pm.maxchildren 的值需要根据服务器内存来设置。一般每个PHP-FPM进程占用大约20-50MB内存所以,pm.maxchildren = 可用内存 / 每个进程内存。比如服务器有2GB可用内存每个进程占用40MB那么,pm.max_children = 2048 / 40 ≈ 50。

5.2 慢日志

开启PHP-FPM的慢日志能记录执行慢的PHP脚本方便排查性能问题。

; 慢日志文件路径
slowlog = /var/log/php-fpm/slow.log

; 慢日志阈值(超过这个时间的请求会被记录)
request_slowlog_timeout = 3s

6. 完整配置示例

下面是一个完整的Nginx配置示例包含了上面介绍的各种优化:

# 全局配置
user nginx;
worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

# 事件配置
events {
    use epoll;
    worker_connections 10240;
    multi_accept on;
}

# HTTP配置
http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    # 日志格式
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    
    access_log /var/log/nginx/access.log main;
    
    # 性能优化
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65s;
    keepalive_requests 100;
    client_header_timeout 10s;
    client_body_timeout 10s;
    send_timeout 10s;
    client_max_body_size 10m;
    
    # 隐藏版本号
    server_tokens off;
    
    # Gzip压缩
    gzip on;
    gzip_comp_level 6;
    gzip_min_length 1k;
    gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/xml image/svg+xml;
    gzip_vary on;
    gzip_proxied any;
    gzip_disable "MSIE [1-6]\.";
    
    # 打开文件缓存
    open_file_cache max=65535 inactive=60s;
    open_file_cache_min_uses 2;
    open_file_cache_valid 60s;
    open_file_cache_errors on;
    
    # 限流
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
    limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
    
    # 服务器配置
    server {
        listen 80;
        server_name example.com www.example.com;
        root /var/www/html;
        index index.php index.html index.htm;
        
        # 限流
        limit_conn conn_limit 20;
        limit_req zone=req_limit burst=20 nodelay;
        limit_req_status 429;
        limit_conn_status 429;
        
        # 禁止访问敏感文件
        location ~ /\. {
            deny all;
            access_log off;
            log_not_found off;
        }
        
        location ~ ~$ {
            deny all;
            access_log off;
            log_not_found off;
        }
        
        location ~ \.(ini|conf|env|log|sql|bak|old)$ {
            deny all;
            access_log off;
            log_not_found off;
        }
        
        # 静态文件缓存
        location ~* \.(jpg|jpeg|png|gif|ico|webp|svg)$ {
            expires 30d;
            add_header Cache-Control "public, no-transform";
        }
        
        location ~* \.(css|js)$ {
            expires 7d;
            add_header Cache-Control "public, no-transform";
        }
        
        location ~* \.(woff|woff2|ttf|otf|eot)$ {
            expires 30d;
            add_header Cache-Control "public, no-transform";
        }
        
        # PHP处理
        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;
            
            # 禁止不安全的HTTP方法
            if ($request_method !~ ^(GET|POST)$) {
                return 405;
            }
        }
        
        # 伪静态
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
    }
}

写在最后

以上就是Nginx高性能Web服务器配置优化指南。Nginx的优化是一个持续的过程需要根据服务器配置网站需求和访问情况不断调整和优化才能发挥Nginx的最佳性能。

上面介绍的这些优化配置都是比较通用和基础的适用于大多数Web网站。但是具体的配置值还需要根据实际情况进行调整比如,workerconnectionspm.maxchildren,等都需要根据服务器配置和预期并发数来设置。

另外优化的同时也要注意安全不能为了性能而忽略安全。合理的安全加固能保护网站免受各种攻击是非常重要,的。

希望这篇指南能帮到大家优化自己的Nginx服务器提高网站性能和安全性。如果有什么问题或者建议欢迎在评论区留言和我一起讨论。

最后提醒大家几句:

  1. 修改配置前备份:修改Nginx配置前一定要备份原配置文件避免修改出错导致网站无法访问。
  2. 修改后测试:修改配置后使用,nginx -t,测试配置是否正确确认无误后再重载配置。
  3. 根据实际情况调整:上面的配置值只是参考需要根据实际情况进行调整不要盲目照搬。
  4. 持续监控和优化:网站性能优化是一个持续的过程需要持续监控网站性能根据监控数据不断调整和优化。

祝大家都能配置出高性能高安全的Nginx服务器让网站访问速度更快更稳定!