Nginx 502 Bad Gateway常见原因和解决办法
前言
网站突然打不开了,浏览器显示"502 Bad Gateway"?这是Nginx最常见的报错之一。本文讲502是什么意思、常见原因、怎么排查和解决。
一、502是什么意思
502 Bad Gateway = Nginx作为代理,从后端服务器(比如PHP-FPM)拿不到正常的响应。
简单说:Nginx收到了你的请求,然后去问后端"给我数据",后端没理它或者报错了,Nginx就返回502。
二、常见原因
原因1:PHP-FPM没启动
后端PHP服务没跑,Nginx找不到人。
检查:
ps aux | grep php-fpm
没输出就是没启动。
启动:
systemctl start php-fpm
或者:
service php-fpm start
原因2:PHP-FPM端口不对
Nginx配置里写的PHP-FPM地址不对。
比如:
fastcgi_pass 127.0.0.1:9000;
但PHP-FPM实际监听的是 /tmp/php-cgi.sock。
检查PHP-FPM监听:
netstat -tlnp | grep php-fpm
或者:
ss -tlnp | grep php-fpm
原因3:PHP代码报错
PHP代码有致命错误,直接挂了。
看PHP错误日志:
tail -f /var/log/php-fpm/www-error.log
或者:
tail -f /var/log/php/error.log
原因4:PHP超时了
程序跑太慢,超过Nginx或PHP-FPM的超时时间。
改Nginx超时:
fastcgi_read_timeout 300;
改PHP-FPM超时:
request_terminate_timeout = 300
原因5:PHP-FPM进程数不够
请求太多,PHP-FPM忙不过来。
看进程数:
ps aux | grep php-fpm | wc -l
改配置:
pm.max_children = 50
pm.start_servers = 20
原因6:内存不够了
PHP进程占满内存,系统把PHP杀了。
看内存:
free -h
看dmesg:
dmesg | grep oom
三、排查步骤
第一步:看Nginx错误日志
tail -f /var/log/nginx/error.log
常见报错:
| 报错 | 含义 |
|---|---|
| connect() failed (111: Connection refused) | PHP-FPM没启动 |
| Primary script unknown | 文件路径不对 |
| upstream timed out | PHP超时了 |
| recv() failed (104: Connection reset by peer) | PHP-FPM挂了 |
第二步:看PHP-FPM状态
systemctl status php-fpm
看是不是running。
第三步:看PHP错误日志
tail -f /var/log/php-fpm/www-error.log
看PHP代码有没有报错。
第四步:看系统资源
top
free -h
df -h
看CPU、内存、磁盘够不够。
四、常见解决方法
方法1:重启PHP-FPM
systemctl restart php-fpm
方法2:改Nginx配置
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_read_timeout 300;
fastcgi_send_timeout 300;
}
方法3:改PHP-FPM进程数
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
改完重启:
systemctl restart php-fpm
方法4:开PHP错误显示
display_errors = On
error_reporting = E_ALL
五、常见坑
坑1:只重启Nginx,不重启PHP-FPM
502是后端的问题,重启Nginx没用。
正确: 重启PHP-FPM。
坑2:文件路径不对
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
错! 应该是:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
坑3:PHP-FPM版本不对
装了PHP7但Nginx还找PHP5的sock。
检查:
ls -la /var/run/php/
坑4:权限问题
PHP-FPM没权限读网站目录的文件。
解决:
chown -R www:www /www/wwwroot/
总结
记住:
- 502 = Nginx拿不到后端响应
- 先看Nginx错误日志
- 再看PHP-F启没启动
- 然后看PHP代码有没有报错
- 最后看系统资源够不够
最快排查:
tail -f /var/log/nginx/error.log
systemctl status php-fpm
遇到问题加QQ23979811 协助处理
Nginx报"no input file specified"错误解决
前言
访问 PHP 页面,直接报 "No input file specified",意思是 PHP-FPM 找不到要执行的 PHP 文件。这是 Nginx 配置里 root 路径不对导致的。
报错长什么样
页面上直接显示:
No input file specified.
没有其他信息,就这么一句话。
常见原因
原因1:root 路径不对
PHP location 里的 root 和 server 里的 root 不一致。
错误示例:
server {
root /var/www/html;
location ~ \.php$ {
fastcgi_param SCRIPT_FILENAME /var/www/php$fastcgi_script_name;
}
}
这样 PHP 找文件的时候就找错目录了。
正确做法:
server {
root /var/www/html;
location ~ \.php$ {
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
用 $document_root 自动取 server 里的 root。
原因2:文件真的不存在
URL 对应的 PHP 文件根本就没有。
检查:
ls /var/www/html/test.php
原因3:文件权限不对
文件存在,但 Nginx/PHP-FPM 读不了。
解决: 确保文件权限是 644,目录是 755,属主是 www。
完整正确的配置
server {
listen 80;
server_name www.example.com;
root /var/www/html;
index index.php index.html;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
排查步骤
第一步:确认文件在不在
ls /var/www/html/test.php
第二步:看 Nginx 错误日志
tail -f /var/log/nginx/error.log
访问一下报错的页面,看日志里写的路径是什么。
第三步:确认 root 路径
grep root /etc/nginx/conf.d/你的站点.conf
常见坑
坑1:fastcgi_param 写错了
写成了 $request_filename 或者其他变量。
解决: 一定要用 $document_root$fastcgi_script_name。
坑2:伪静态和 PHP 冲突
配了伪静态,导致 PHP 请求被重写到别的地方了。
解决: 确保伪静态规则在 PHP location 之前,而且 PHP location 能正常匹配到 .php 请求。
坑3:多站点 root 不一致
A 站点的 PHP 请求跑到 B 站点去了。
原因: 多个站点的 root 配置不对。
解决: 每个站点的 root 都写清楚,别共用。
坑4:PHP-FPM 配置不对
PHP-FPM 的 www.conf 里的 listen 路径和 Nginx 配置的不一致。
解决: 确认两边的 socket 路径一样。
总结
90% 的情况都是 root 路径不对。
检查这三点:
- root 路径写对了没
- 文件真的存在不
- 文件权限对不对
记住: PHP 配置里一定要用 $document_root$fastcgi_script_name,别写死路径。
遇到问题加QQ23979811 协助处理
Nginx反向代理配置,代理后端PHP服务
前言
LNMP 架构里,Nginx 收到 PHP 请求之后,要转发给 PHP-FPM 处理。这个转发的配置就是 fastcgi_pass。本文讲一下完整的 Nginx 代理 PHP 服务配置。
两种代理方式
Nginx 代理后端服务有两种方式:
- proxy_pass:代理 HTTP 服务(比如 Node.js、Java、Python)
- fastcgi_pass:代理 FastCGI 服务(就是 PHP-FPM)
PHP 用的是 fastcgi_pass,不是 proxy_pass,别搞混了。
基础配置
完整 LNMP 配置示例
server {
listen 80;
server_name www.example.com;
root /var/www/html;
index index.php index.html;
# 访问根目录
location / {
try_files $uri $uri/ =404;
}
# PHP 请求转发给 PHP-FPM
location ~ \.php$ {
root /var/www/html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
关键参数说明
| 参数 | 作用 |
|---|---|
fastcgi_pass 127.0.0.1:9000 |
PHP-FPM 监听的地址和端口 |
fastcgi_pass unix:/run/php-fpm/www.sock |
用 socket 文件方式(更高效) |
fastcgi_index index.php |
默认首页 |
SCRIPT_FILENAME |
PHP 文件的完整路径 |
include fastcgi_params |
引入其他参数 |
socket 方式 vs 端口方式
端口方式(TCP)
fastcgi_pass 127.0.0.1:9000;
优点:跨服务器可以用
缺点:多了一层 TCP 开销,稍微慢一点
Socket 方式(Unix Domain Socket)
fastcgi_pass unix:/run/php-fpm/www.sock;
优点:更快,少了 TCP 开销
缺点:只能在同一台服务器上用
生产环境推荐用 socket 方式,更快。
完整生产环境配置
server {
listen 443 ssl http2;
server_name www.example.com;
ssl_certificate /etc/nginx/ssl/www.crt;
ssl_certificate_key /etc/nginx/ssl/www.key;
root /var/www/html;
index index.php index.html;
# 日志
access_log /var/log/nginx/www.access.log;
error_log /var/log/nginx/www.error.log;
# 静态资源直接返回
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 30d;
}
# PHP 请求转发
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 超时设置
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
}
# 禁止访问 .ht 等文件
location ~ /\.ht {
deny all;
}
}
常见坑
坑1:SCRIPT_FILENAME 路径不对
配置了 SCRIPT_FILENAME /var/www/html$fastcgi_script_name;,但 root 不是这个路径。
原因: 写死了路径,换个目录就错了。
解决: 用 $document_root:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
坑2:socket 路径不一致
Nginx 配置里写的 socket 路径和 PHP-FPM 实际的不一致。
检查 PHP-FPM 的 socket 路径:
grep listen /etc/php-fpm.d/www.conf
确保两边路径一模一样。
坑3:PHP 不解析,直接下载
访问 index.php,浏览器直接下载了文件,没解析。
原因: Nginx 没把 .php 请求转发给 PHP-FPM。
检查: 配置里有没有 location ~ \.php$ 这一段,有没有 fastcgi_pass。
坑4:404 Not Found
访问 PHP 文件报 404。
原因: SCRIPT_FILENAME 路径不对,PHP-FPM 找不到文件。
解决: 确认 root 和 SCRIPT_FILENAME 配置正确。
检查配置并重载
nginx -t
nginx -s reload
总结
| 配置项 | 说明 |
|---|---|
fastcgi_pass |
PHP-FPM 地址(端口或socket) |
SCRIPT_FILENAME |
PHP 文件完整路径 |
fastcgi_params |
其他参数集合 |
expires |
静态资源缓存 |
| 超时设置 | fastcgi_connect_timeout 等 |
记住: PHP 用 fastcgi_pass,不是 proxy_pass,别搞混了。
遇到问题加QQ23979811 协助处理
Nginx报502 Bad Gateway完整排查思路(PHP-FPM场景)
前言
502 Bad Gateway 是 Nginx 最常见的报错之一,尤其是 LNMP 架构下,Nginx 把 PHP 请求转发给 PHP-FPM,PHP-FPM 出问题了 Nginx 就报 502。本文讲一下完整的排查思路。
502 是什么意思
502 表示 Nginx 作为反向代理,去请求后端服务(PHP-FPM)的时候,后端没响应或者报错了。
注意: 502 不是 Nginx 的问题,是后端 PHP-FPM 的问题。
排查步骤
第一步:检查 PHP-FPM 服务是否在运行
systemctl status php-fpm
如果显示 inactive (dead),说明 PHP-FPM 挂了,启动它:
systemctl start php-fpm
systemctl enable php-fpm
第二步:检查 Nginx 和 PHP-FPM 的通信配置
看 Nginx 配置里的 fastcgi_pass 对不对:
grep fastcgi_pass /etc/nginx/nginx.conf
常见的配置:
# 用 socket 文件
fastcgi_pass unix:/run/php-fpm/www.sock;
# 用 TCP 端口
fastcgi_pass 127.0.0.1:9000;
问题1:socket 文件路径不对
Nginx 配置里写的 socket 路径和 PHP-FPM 实际的不一致。
PHP-FPM 的 socket 路径在 /etc/php-fpm.d/www.conf 里:
grep listen /etc/php-fpm.d/www.conf
确保两边路径一致。
问题2:端口被占
如果用 9000 端口,检查一下是不是被别的进程占了:
lsof -i:9000
第三步:看错误日志
Nginx 错误日志:
tail -f /var/log/nginx/error.log
PHP-FPM 错误日志:
tail -f /var/log/php-fpm/error.log
PHP 慢日志:
tail -f /var/log/php-fpm/www-slow.log
根据日志里的报错信息找原因。
第四步:常见原因
原因1:PHP-FPM 进程数不够
访问量大的时候,PHP-FPM 进程都被占满了,新请求排队超时。
解决: 增加 PHP-FPM 进程数。
编辑 /etc/php-fpm.d/www.conf:
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
改完重启:
systemctl restart php-fpm
原因2:PHP 脚本执行超时
PHP 脚本执行时间太长,超过了 Nginx 的超时时间。
解决: 调大超时时间。
Nginx 配置里:
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
PHP 配置里:
max_execution_time = 300
原因3:PHP 内存不足
PHP-FPM 进程内存溢出,导致进程崩溃。
解决: 调大 PHP 内存限制:
memory_limit = 256M
或者减少 PHP-FPM 进程数,避免内存不够。
原因4:文件权限不对
Nginx 运行的用户和 PHP-FPM 运行的用户不一致,导致 PHP-FPM 读不到文件。
解决: 确保 Nginx 和 PHP-FPM 用同一个用户(一般是 www)。
PHP-FPM 配置 /etc/php-fpm.d/www.conf:
user = www
group = www
然后把网站文件的属主改成 www:
chown -R www:www /var/www/html
第五步:重启所有服务
改完配置后重启:
systemctl restart php-fpm
systemctl restart nginx
常见坑
坑1:只重启了 Nginx
改了 PHP 配置但只重启了 Nginx,PHP-FPM 还是老配置。
解决: PHP 配置改了要重启 PHP-FPM,Nginx 配置改了要重启 Nginx。
坑2:socket 文件权限不对
PHP-FPM 的 socket 文件权限是 600,Nginx 用户读不到。
解决: 改 socket 文件权限:
listen.mode = 0666
或者改 socket 文件的属主:
listen.owner = www
listen.group = www
坑3:PHP-FPM 挂了但没自动重启
PHP-FPM 进程崩溃了,没人自动拉起来。
解决: 配置 systemd 自动重启:
systemctl edit php-fpm
加:
[Service]
Restart=always
RestartSec=2
总结
502 排查步骤:
- 先看 PHP-FPM 是不是挂了 →
systemctl status php-fpm - 再看 Nginx 配置对不对 → fastcgi_pass 路径/端口
- 看错误日志 → Nginx error.log + PHP-FPM error.log
- 常见原因 → 进程数不够、超时太短、权限不对、内存不足
记住:502 问题出在后端,不是 Nginx 的锅。
遇到问题加QQ23979811 协助处理
Nginx报502 Bad Gateway完整排查思路(PHP-FPM场景)
Nginx 出现 502 Bad Gateway 是最常见的报错之一,90% 的情况都是 PHP-FPM 出了问题。下面是完整的排查思路,按顺序一步步来,基本都能解决。
1. 先看 PHP-FPM 是否在运行
systemctl status php-fpm
如果显示 failed 或 inactive,直接重启:
systemctl restart php-fpm
注意:CentOS 7 一般是
php-fpm,Ubuntu 可能是php7.4-fpm之类的,看你装的版本。
2. 看 Nginx 错误日志(最关键)
tail -f /var/log/nginx/error.log
常见错误信息:
错误1:connect() failed (111: Connection refused) while connecting to upstream
说明 PHP-FPM 没启动,或者监听地址不对。
错误2:upstream timed out
PHP 脚本执行超时了,或者 PHP-FPM 进程不够用。
错误3:Primary script unknown
Nginx 配置里的 SCRIPT_FILENAME 路径不对,找不到 PHP 文件。
3. 检查 Nginx 配置是否正确
nginx -t
如果显示 test is successful 说明配置语法没问题。
重点检查 fastcgi_pass 这一行:
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000; # 或者 unix:/run/php-fpm/www.sock
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
常见问题:
- fastcgi_pass 地址和 PHP-FPM 实际监听地址不一致
- SCRIPT_FILENAME 路径写错了
4. 检查 PHP-FPM 监听地址
netstat -tlnp | grep php-fpm
或者:
ss -tlnp | grep php-fpm
看 PHP-FPM 是监听在 9000 端口还是 unix sock 文件,然后和 Nginx 配置里的 fastcgi_pass 对应上。
5. 检查 PHP-FPM 进程数是否够
看 PHP-FPM 配置:
vi /etc/php-fpm.d/www.conf
重点参数:
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
如果访问量大,进程数不够就会 502。
6. 检查 PHP 错误日志
tail -f /var/log/php-fpm/www-error.log
有时候 PHP 代码本身报错,也会导致 502。
7. 其他常见原因
磁盘满了
df -h
内存不够
free -h
如果内存不足,PHP-FPM 进程会被杀掉,也会 502。
SELinux 没关
参考我之前的文章,关掉 SELinux 试试。
排查顺序总结
- 重启 PHP-FPM → 看能不能恢复
- 看 Nginx 错误日志 → 定位具体错误
- 检查 Nginx 配置 → fastcgi_pass 和 SCRIPT_FILENAME
- 检查 PHP-FPM 状态 → 监听地址、进程数
- 检查系统资源 → 磁盘、内存
- 检查 SELinux
遇到服务器、Nginx、MySQL 报错,可以加微信远程协助排查问题。
PHP 性能优化:从代码到部署的完整指南
前言
PHP 性能优化是每个 PHP 开发者都绕不开的话题。很多人觉得 PHP 性能差,但实际上通过合理的优化,PHP 应用完全可以达到很高的性能水平。本文从代码层面到部署层面,带你完整梳理 PHP 性能优化的思路。
一、代码层面优化
1. 避免在循环中做数据库查询
// 慢:循环中查询数据库
foreach ($users as $user) {
$order = $db->query("SELECT * FROM orders WHERE user_id = {$user['id']}");
}
// 快:一次性查询,然后用数组映射
$userIds = array_column($users, 'id');
$orders = $db->query("SELECT * FROM orders WHERE user_id IN (" . implode(',', $userIds) . ")")->fetchAll();
$orderMap = array_column($orders, null, 'user_id');
2. 用生成器处理大数据
// 慢:一次性加载所有数据到内存
$users = $db->query("SELECT * FROM big_table")->fetchAll();
// 快:用生成器逐行处理
function getUsers() {
$stmt = $pdo->query("SELECT * FROM big_table");
while ($row = $stmt->fetch()) {
yield $row;
}
}
3. 字符串拼接 vs implode
// 慢:频繁拼接字符串
$str = '';
foreach ($items as $item) {
$str .= $item . ',';
}
// 快:用数组收集最后拼接
$parts = [];
foreach ($items as $item) {
$parts[] = $item;
}
$str = implode(',', $parts);
二、PHP 配置优化
1. OPcache 必开
OPcache 是 PHP 性能提升最大的一个扩展,没有之一。
; php.ini
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
开启 OPcache 后,PHP 脚本会被编译成字节码缓存起来,避免每次请求都重新编译。性能提升通常在 2-5 倍。
2. 合理设置内存限制
memory_limit = 256M
不要设置太大,也不要太小。根据你的应用实际情况调整。
三、数据库优化
1. 开启慢查询日志
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
找出慢查询,然后针对性优化。
2. 使用持久化连接要谨慎
// 不一定更快,可能反而更慢
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass', [
PDO::ATTR_PERSISTENT => true
]);
持久化连接在高并发场景下可能导致连接耗尽,要根据实际情况测试。
四、部署层面优化
1. 使用 PHP-FPM 优化
; php-fpm/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
根据服务器内存调整 max_children,每个 PHP-FPM 进程大约占用 20-40MB 内存。
2. Nginx 开启 gzip
gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1000;
3. 静态文件 CDN 加速
把图片、CSS、JS 等静态资源放到 CDN 上,减轻服务器压力。
五、性能监控工具
- Xdebug:代码性能分析,找出瓶颈函数
- Blackfire:更专业的性能分析工具
- New Relic:APM 应用性能监控
- ab / wrk:压力测试工具
总结
PHP 性能优化的核心思路:
- 先找出瓶颈在哪里,不要盲目优化
- 代码层面:减少数据库查询、减少内存占用
- 配置层面:OPcache 必开
- 部署层面:PHP-FPM、Nginx、数据库都要调优
- 用工具量化优化效果
性能优化是一个持续迭代的过程,不要指望一次性优化到位。每次做一点,慢慢积累。