PHP负载均衡需协同会话管理、代码同步、健康检查与进程模型;否则易现502和session丢失。应合理配置php-fpm参数或Swoole/ReactPHP监听地址,使用Redis存session,通过CI/CD统一部署,慎用least_conn,强化应用层健康检查。

PHP 应用要做负载均衡,不是加个 Nginx 就算完事——它必须和你的会话管理、代码同步、健康检查、进程模型四者咬合,否则流量一上来,502 和 session 丢失就会交替出现。
为什么 Nginx upstream 配置后还是 502?
常见现象是:Nginx 日志里反复出现 upstream prematurely closed connection 或 Connection refused,但后端 PHP 进程明明在跑。根本原因往往不是网络不通,而是 PHP 服务没按预期长期存活。
- 如果你用的是传统
php-fpm,确认pm.max_children和pm.start_servers设置合理;过低会导致请求排队超时,过高则触发 OOM Killer 杀掉子进程 - 若用
Swoole或ReactPHP,必须确保服务以 daemon 模式启动且监听0.0.0.0(而非127.0.0.1),否则 Nginx 无法通过内网 IP 访问 -
proxy_read_timeout必须 ≥ 后端最长响应时间;默认 60 秒对含数据库慢查询或外部 HTTP 调用的服务远远不够
session 丢失的真正根源不在 Nginx
很多人以为加个 ip_hash 就能保住 session,结果用户刷新几次就登出——因为 CDN、NAT 网关、移动网络会让真实 IP 频繁变化,ip_hash 只是掩耳盗铃。
- 正确做法是关闭所有节点的本地 session 存储:把
session.save_handler设为redis,session.save_path指向统一 Redis 实例(如tcp://192.168.1.20:6379?database=1) - 避免用
memcached存 session:它不支持原子 TTL 更新,高并发下易出现“假过期”导致用户被强制登出 - 如果必须兼容旧逻辑,可在应用层写一个轻量级 session 代理中间件,把
PHPSESSID解密后映射到 Redis key,而不是依赖 PHP 内置机制
多服务器间代码不同步,比宕机更危险
你可能遇到:A 服务器修复了一个支付 bug,B 服务器还在返回错误订单号——这不是负载均衡的问题,是部署流程失控。
立即学习“PHP免费学习笔记(深入)”;
- 禁用手工
scp或rsync推送代码;它们没有原子性,推送中途失败会导致半新半旧状态 - 用 Git 钩子 +
git archive打包 +ssh解压方式,确保每次上线都是完整快照;或直接走 CI/CD 流水线构建 Docker 镜像 - 所有服务器应从同一配置中心拉取运行时参数(如数据库地址、API 密钥),而非硬编码在
config.php里
least_conn 不等于“最空闲”,它只看连接数
在 ReactPHP 或 Swoole 场景下,least_conn 策略容易误导人:一个进程可能只有 2 个连接,但正在处理一个耗时 10 秒的图像压缩任务;另一个有 8 个连接,却全是毫秒级 API 查询。
-
least_conn对 CPU 密集型任务几乎无效;它更适合 I/O 密集、连接生命周期短的场景(如 WebSocket 心跳) - 真要动态感知负载,得让每个 PHP 工作进程主动上报指标(如
memory_get_usage()、sys_getloadavg()),由独立调度器(如 Consul + Fabio)做决策 - 简单替代方案:用
weight手动调优,比如给 SSD 服务器设weight=5,HDD 服务器设weight=2,比盲目依赖自动算法更可控
最常被跳过的环节是健康检查的粒度——max_fails=1 fail_timeout=10s 看似稳妥,但一次 GC 停顿或磁盘 IO 尖峰就可能误判节点下线;实际生产中建议用应用层探针(如 /health?full=1)验证数据库连通性+Redis 可写+本地缓存命中率,再决定是否剔除节点。



















