设置 FastCGI 代理

Nginx 可以通过 FastCGI 协议与 PHP、Python 等后端应用程序通信,本章节主要介绍如何配置 PHP FastCGI 代理。

安装 PHP-FPM

Ubuntu/Debian

sudo apt update
sudo apt install php-fpm

# 启动 PHP-FPM
sudo systemctl start php7.4-fpm
sudo systemctl enable php7.4-fpm

CentOS/RHEL

sudo yum install php-fpm

# 启动 PHP-FPM
sudo systemctl start php-fpm
sudo systemctl enable php-fpm

macOS

brew install php

# 启动 PHP-FPM
brew services start php

基本配置

简单的 FastCGI 配置

server {
    listen       80;
    server_name  localhost;

    root   /usr/share/nginx/html;
    index  index.php index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }

    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 指令说明

指令说明
fastcgi_pass指定 FastCGI 服务器地址
fastcgi_index指定默认索引文件
fastcgi_param设置传递给 FastCGI 服务器的参数
fastcgi_params包含 FastCGI 参数文件

常用 FastCGI 参数

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REQUEST_SCHEME     $scheme;

fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

fastcgi_param  REDIRECT_STATUS    200;

使用 Unix Socket

配置 PHP-FPM

编辑 /etc/php/7.4/fpm/pool.d/www.conf

listen = /var/run/php/php7.4-fpm.sock

配置 Nginx

location ~ \.php$ {
    fastcgi_pass   unix:/var/run/php/php7.4-fpm.sock;
    fastcgi_index  index.php;
    include        fastcgi_params;
}

FastCGI 缓存

定义缓存路径

fastcgi_cache_path /path/to/cache levels=1:2 keys_zone=FASTCGI:100m inactive=60m;

启用缓存

location ~ \.php$ {
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    fastcgi_cache FASTCGI;
    fastcgi_cache_valid 200 60m;
}

FastCGI 超时设置

location ~ \.php$ {
    fastcgi_connect_timeout 60s;
    fastcgi_send_timeout 180s;
    fastcgi_read_timeout 180s;
}

完整配置示例

基本 PHP 配置

server {
    listen       80;
    server_name  localhost;

    root   /usr/share/nginx/html;
    index  index.php index.html index.htm;

    charset utf-8;

    location / {
        try_files $uri $uri/ =404;
    }

    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;
    }

    location ~ /\.ht {
        deny  all;
    }
}

高级 PHP 配置

server {
    listen       80;
    server_name  localhost;

    root   /usr/share/nginx/html;
    index  index.php index.html index.htm;

    charset utf-8;

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

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

    # 静态文件缓存
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    # PHP 文件处理
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.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 60s;
        fastcgi_send_timeout 180s;
        fastcgi_read_timeout 180s;

        # 缓冲区设置
        fastcgi_buffering on;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 256 16k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
        fastcgi_intercept_errors on;
    }

    # 主页面
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
}

测试 PHP

创建测试文件

echo "<?php phpinfo(); ?>" | sudo tee /usr/share/nginx/html/info.php

访问测试

在浏览器中访问 http://localhost/info.php,应该看到 PHP 信息页面。

删除测试文件

sudo rm /usr/share/nginx/html/info.php

故障排查

检查 PHP-FPM 状态

sudo systemctl status php-fpm

检查 PHP-FPM 日志

sudo tail -f /var/log/php-fpm/error.log

检查 Nginx 错误日志

sudo tail -f /var/log/nginx/error.log

检查 Socket 权限

ls -la /var/run/php/

检查 PHP-FPM 配置

php-fpm -t

常见问题

1. 502 Bad Gateway

# 检查 PHP-FPM 是否运行
sudo systemctl status php-fpm

# 检查 Socket 文件
ls -la /var/run/php/

# 检查 Nginx 配置
sudo nginx -t

2. 文件未找到

location ~ \.php$ {
    try_files $uri =404;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

3. 权限问题

# 设置正确的权限
sudo chown -R www-data:www-data /usr/share/nginx/html
sudo chmod -R 755 /usr/share/nginx/html

4. 超时问题

location ~ \.php$ {
    fastcgi_connect_timeout 60s;
    fastcgi_send_timeout 180s;
    fastcgi_read_timeout 180s;
}

最佳实践

  1. 使用 try_files:避免直接传递 PHP 文件
  2. 设置超时:避免长时间等待
  3. 启用缓存:提高性能
  4. 限制访问:保护敏感文件
  5. 监控日志:及时发现异常
  6. 定期更新:保持 PHP 和 Nginx 最新