PHP-FPM与Nginx的配置调优:FastCGI参数、缓冲区大小与Gzip压缩设置

好的,现在开始我们的PHP-FPM与Nginx配置调优讲座。今天我们将深入探讨如何通过优化FastCGI参数、缓冲区大小和Gzip压缩设置,来提升PHP-FPM与Nginx组合的性能。

一、FastCGI参数调优:连接Nginx与PHP-FPM的桥梁

FastCGI参数是Nginx与PHP-FPM之间通信的关键,合理的配置可以显著提升性能和安全性。

  1. fastcgi_pass: 指定PHP-FPM监听的地址和端口。

    • Unix Domain Socket: 建议使用,因为它避免了网络开销,速度更快。

      fastcgi_pass unix:/run/php/php7.4-fpm.sock; # 根据你的PHP版本调整
    • TCP Socket: 如果PHP-FPM和Nginx不在同一台服务器,则需要使用TCP Socket。

      fastcgi_pass 127.0.0.1:9000;
  2. fastcgi_index: 指定默认的PHP文件。通常是index.php

    fastcgi_index index.php;
  3. fastcgi_param: 设置传递给PHP-FPM的参数。以下是一些重要的参数:

    • SCRIPT_FILENAME: 指定PHP脚本的完整路径。
    • SCRIPT_NAME: 指定PHP脚本相对于网站根目录的路径。
    • REQUEST_URI: 客户端请求的URI。
    • DOCUMENT_ROOT: 网站的根目录。
    • QUERY_STRING: URL中的查询字符串。
    • REQUEST_METHOD: HTTP请求方法(GET、POST等)。
    • CONTENT_TYPE: HTTP请求的Content-Type。
    • CONTENT_LENGTH: HTTP请求的Content-Length。

    一个典型的fastcgi_param配置如下:

    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param SCRIPT_NAME $fastcgi_script_name;
    fastcgi_param REQUEST_URI $request_uri;
    fastcgi_param DOCUMENT_ROOT $document_root;
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_param REQUEST_METHOD $request_method;
    fastcgi_param CONTENT_TYPE $content_type;
    fastcgi_param CONTENT_LENGTH $content_length;
  4. fastcgi_read_timeout: 设置Nginx等待PHP-FPM响应的超时时间。 如果PHP脚本执行时间过长,可能会导致504 Gateway Timeout错误。 增加此值可以解决这类问题,但同时也意味着Nginx会等待更长时间。

    fastcgi_read_timeout 300; # 单位:秒
  5. fastcgi_connect_timeout: 设置Nginx连接到PHP-FPM的超时时间。

    fastcgi_connect_timeout 60; #单位:秒
  6. fastcgi_send_timeout: 设置Nginx向PHP-FPM发送请求的超时时间。

    fastcgi_send_timeout 60; #单位:秒
  7. fastcgi_buffers and fastcgi_buffer_size: 控制Nginx用于读取PHP-FPM响应的缓冲区大小。

    • fastcgi_buffers: 设置用于读取PHP-FPM响应的缓冲区的数量和大小。 例如,fastcgi_buffers 16 4k 表示使用16个4KB的缓冲区。
    • fastcgi_buffer_size: 设置单个缓冲区的大小。

    合理的缓冲区大小可以避免频繁的磁盘I/O,提升性能。 通常,fastcgi_buffer_size 可以设置为页面大小(例如,4KB或8KB),而 fastcgi_buffers 的数量可以根据应用程序的响应大小进行调整。 如果Nginx错误日志中出现 "upstream sent too big header" 错误,则需要增加 fastcgi_buffer_size

    fastcgi_buffers 16 16k;
    fastcgi_buffer_size 16k;
  8. fastcgi_cache and fastcgi_cache_valid: 启用FastCGI缓存。 可以将PHP脚本的响应缓存到磁盘上,以减少PHP-FPM的负载。 适用于静态内容或不经常更新的内容。

    fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=php_cache:10m inactive=60m max_size=1g;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    fastcgi_cache_valid 200 302 60m;
    fastcgi_cache_valid 301 1h;
    fastcgi_cache_valid any 1m;
    fastcgi_cache php_cache;
    add_header X-Cache $upstream_cache_status;
    • fastcgi_cache_path: 指定缓存目录、缓存级别、缓存区域名称、非活跃时间、最大缓存大小。
    • fastcgi_cache_key: 定义缓存Key的生成方式。
    • fastcgi_cache_valid: 指定不同HTTP状态码的缓存时间。
    • fastcgi_cache: 启用缓存区域。
    • add_header X-Cache: 添加一个HTTP头,显示缓存状态 (HIT, MISS, BYPASS, EXPIRED, STALE)。

    注意: 启用FastCGI缓存前,需要创建缓存目录,并设置正确的权限。 mkdir -p /tmp/nginx_cache; chown nginx:nginx /tmp/nginx_cache (假设Nginx运行用户为nginx)

  9. fastcgi_cache_bypass and fastcgi_no_cache: 控制FastCGI缓存的绕过和禁用。 可以根据请求的Cookie、Header等信息,动态地绕过或禁用缓存。 例如,对于登录用户,可以禁用缓存。

    fastcgi_cache_bypass $skip_cache;
    fastcgi_no_cache $skip_cache;
    set $skip_cache 0;
    if ($http_cookie ~* "wordpress_logged_in_|comment_author_") {
        set $skip_cache 1;
    }

二、缓冲区大小调优:高效的数据传输

缓冲区大小直接影响Nginx处理请求的效率。 适当的缓冲区大小可以减少磁盘I/O,提升性能。

  1. client_body_buffer_size: 设置客户端请求body的缓冲区大小。 如果客户端上传的文件较大,需要增加此值。

    client_body_buffer_size 10M;
  2. client_max_body_size: 设置客户端请求body的最大大小。 用于防止DDoS攻击和上传过大的文件。

    client_max_body_size 100M;
  3. proxy_buffers and proxy_buffer_size: 控制Nginx作为反向代理时,用于读取上游服务器响应的缓冲区大小。 与fastcgi_buffersfastcgi_buffer_size类似,但用于代理场景。

    proxy_buffers 8 16k;
    proxy_buffer_size 16k;
  4. postpone_output: 允许Nginx在发送HTTP头之前,先缓冲一部分响应内容。 可以减少TCP连接的建立次数,提升性能。

    postpone_output 1460; # 通常设置为MTU大小
  5. send_lowat: 设置Nginx发送数据的最小字节数。 如果发送的数据小于此值,Nginx会等待更多的数据再发送。 可以减少小数据包的发送,提升网络利用率。

    send_lowat 1500; # 通常设置为MTU大小

三、Gzip压缩设置:减少网络传输量

Gzip压缩可以显著减少HTTP响应的大小,从而加快页面加载速度。

  1. gzip: 启用或禁用Gzip压缩。

    gzip on;
  2. gzip_types: 指定需要进行Gzip压缩的文件类型。 通常包括text/html, text/css, application/javascript, application/json, application/xml 等。

    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/xml application/xml+rss text/javascript;
  3. gzip_comp_level: 设置Gzip压缩级别。 取值范围为1-9,1表示最快的压缩速度,9表示最高的压缩比。 通常设置为4-6,以平衡压缩速度和压缩比。

    gzip_comp_level 6;
  4. gzip_min_length: 设置进行Gzip压缩的最小响应长度。 小于此值的响应不会被压缩。 可以避免压缩过小的文件,因为压缩本身会带来一定的开销。

    gzip_min_length 1000;
  5. gzip_vary: 启用Vary: Accept-Encoding头。 允许缓存服务器根据客户端是否支持Gzip压缩,缓存不同的版本。

    gzip_vary on;
  6. gzip_proxied: 指定在哪些情况下对代理的请求进行Gzip压缩。 常见的取值包括off, expired, no-cache, no-store, private, no_last_modified, no_etag, auth, any

    gzip_proxied any;
  7. gzip_disable: 禁用Gzip压缩的客户端。 可以根据客户端的User-Agent禁用Gzip压缩。 例如,对于一些旧版本的IE浏览器,可能不支持Gzip压缩。

    gzip_disable "MSIE [1-6].";

四、PHP-FPM配置优化:提升PHP执行效率

PHP-FPM的配置直接影响PHP脚本的执行效率和稳定性。

  1. pm: 进程管理方式。 可以选择static, dynamic, 或 ondemand

    • static: 启动固定数量的子进程。 适用于内存充足,并且并发请求量稳定的场景。
    • dynamic: 根据请求量动态调整子进程的数量。 适用于内存有限,或者并发请求量波动的场景。
    • ondemand: 只有在有请求时才启动子进程。 适用于低流量的网站。
    pm = dynamic
  2. pm.max_children: 最大子进程数量。 需要根据服务器的内存和CPU资源进行调整。 过多的子进程会导致内存溢出,过少的子进程会导致请求排队。

    pm.max_children = 50
  3. pm.start_servers: 启动时创建的子进程数量。 适用于dynamic模式。

    pm.start_servers = 10
  4. pm.min_spare_servers: 最小空闲子进程数量。 适用于dynamic模式。 如果空闲子进程数量小于此值,PHP-FPM会启动新的子进程。

    pm.min_spare_servers = 5
  5. pm.max_spare_servers: 最大空闲子进程数量。 适用于dynamic模式。 如果空闲子进程数量大于此值,PHP-FPM会杀死多余的子进程。

    pm.max_spare_servers = 20
  6. pm.max_requests: 每个子进程处理的最大请求数量。 当一个子进程处理的请求数量达到此值时,PHP-FPM会杀死该子进程,并启动一个新的子进程。 可以防止内存泄漏。

    pm.max_requests = 500
  7. request_terminate_timeout: PHP脚本的最大执行时间。 如果PHP脚本执行时间超过此值,PHP-FPM会强制终止该脚本。 可以防止长时间运行的脚本阻塞其他请求。

    request_terminate_timeout = 30s
  8. request_slowlog_timeout: 慢日志记录的阈值。 如果PHP脚本执行时间超过此值,PHP-FPM会将该请求记录到慢日志中。 可以用于分析性能瓶颈。

    request_slowlog_timeout = 3s
  9. slowlog: 慢日志的路径。

    slowlog = /var/log/php-fpm/www-slow.log
  10. php_admin_value[memory_limit]: PHP脚本的内存限制。 需要根据应用程序的需求进行调整。

    php_admin_value[memory_limit] = 128M
  11. php_admin_value[error_log]: PHP错误日志的路径。

    php_admin_value[error_log] = /var/log/php-fpm/www-error.log

五、Nginx配置示例

以下是一个完整的Nginx配置示例,包含了上述所有的优化设置:

server {
    listen 80;
    server_name example.com;
    root /var/www/example.com;
    index index.php index.html index.htm;

    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;

    client_max_body_size 100M;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ .php$ {
        fastcgi_pass unix:/run/php/php7.4-fpm.sock; # 根据你的PHP版本调整
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;

        fastcgi_read_timeout 300;
        fastcgi_connect_timeout 60;
        fastcgi_send_timeout 60;

        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 16k;

        # FastCGI Cache (Optional)
        # fastcgi_cache_bypass $skip_cache;
        # fastcgi_no_cache $skip_cache;
        # set $skip_cache 0;
        # if ($http_cookie ~* "wordpress_logged_in_|comment_author_") {
        #     set $skip_cache 1;
        # }
        # fastcgi_cache php_cache;
        # add_header X-Cache $upstream_cache_status;
    }

    # Static files cache
    location ~* .(jpg|jpeg|gif|png|ico|css|js)$ {
        expires 365d;
        add_header Cache-Control "public, max-age=31536000";
    }

    gzip on;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/xml application/xml+rss text/javascript;
    gzip_comp_level 6;
    gzip_min_length 1000;
    gzip_vary on;
    gzip_proxied any;
    gzip_disable "MSIE [1-6].";
}

六、PHP-FPM配置示例

以下是一个PHP-FPM配置示例(/etc/php/7.4/fpm/pool.d/www.conf):

[www]
user = www-data
group = www-data

listen = /run/php/php7.4-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500

request_terminate_timeout = 30s
request_slowlog_timeout = 3s
slowlog = /var/log/php-fpm/www-slow.log

php_admin_value[memory_limit] = 128M
php_admin_value[error_log] = /var/log/php-fpm/www-error.log

七、监控与调优:持续优化,保持最佳状态

性能调优是一个持续的过程。需要定期监控服务器的性能指标,并根据实际情况进行调整。

  1. CPU使用率: 如果CPU使用率过高,说明服务器的负载过重。 可以尝试增加子进程的数量,或者优化PHP代码。
  2. 内存使用率: 如果内存使用率过高,说明服务器的内存不足。 可以尝试减少子进程的数量,或者增加服务器的内存。
  3. 磁盘I/O: 如果磁盘I/O过高,说明服务器的磁盘性能不足。 可以尝试使用SSD硬盘,或者优化数据库查询。
  4. 网络流量: 如果网络流量过高,说明服务器的网络带宽不足。 可以尝试升级网络带宽,或者使用CDN加速。
  5. Nginx错误日志: 查看Nginx错误日志,可以发现一些潜在的问题,例如 "upstream sent too big header" 错误,或者 "504 Gateway Timeout" 错误。
  6. PHP-FPM慢日志: 查看PHP-FPM慢日志,可以找到执行时间较长的PHP脚本,并进行优化。

监控工具:

  • top: 查看CPU、内存、进程等信息。
  • htop: top 的增强版,提供更友好的界面。
  • iostat: 查看磁盘I/O信息。
  • vmstat: 查看虚拟内存信息。
  • netstat: 查看网络连接信息。
  • iftop: 实时显示网络流量。
  • Nginx Amplify: Nginx官方提供的监控工具。
  • Prometheus and Grafana: 流行的监控和可视化工具。

调优原则:

  • 逐步调整: 每次只调整一个参数,并观察其对性能的影响。
  • 基准测试: 在调整参数之前,进行基准测试,记录当前的性能指标。 在调整参数之后,再次进行基准测试,比较性能的变化。
  • 模拟生产环境: 在测试环境中模拟生产环境的负载,以便更好地评估性能。
  • 关注错误日志: 及时查看Nginx和PHP-FPM的错误日志,解决潜在的问题。

八、总结关键点:优化配置,提升性能

通过合理配置FastCGI参数,调整缓冲区大小,以及启用Gzip压缩,可以显著提升PHP-FPM与Nginx组合的性能,提供更快的页面加载速度和更好的用户体验。定期监控服务器性能并持续优化是保持最佳性能的关键。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注