Nginx proxy_pass末尾斜杠决定是否截断location前缀:不加斜杠则原样转发完整路径(如/api/user),加斜杠则剥离匹配前缀(如location /api/ + proxy_pass .../ → 后端收/user);同时必须配置proxy_http_version 1.1和proxy_set_header Connection ''以支持Hyperf协程长连接,并用proxy_redirect default防止重定向泄露内网地址。

proxy_pass 路径末尾斜杠决定是否截断 location 前缀
Hyperf 默认监听 0.0.0.0:9501,Nginx 代理时若写成 proxy_pass http://127.0.0.1:9501;(无尾部斜杠),请求 /api/user 会被原样转发到后端 /api/user —— 但 Hyperf 的路由注册通常基于根路径(如 @GetMapping("/user")),导致 404。
正确做法是加斜杠:proxy_pass http://127.0.0.1:9501/;。这样 Nginx 会剥离 location / 匹配部分,把 /api/user 转为 /api/user → 实际发给后端的是 /api/user;而 location /api/ { proxy_pass http://127.0.0.1:9501/; } 则会把 /api/user 变成 /user,需确保 Hyperf 路由也按此设计。
- 常见错误现象:浏览器访问正常,但接口返回 404,
curl -v查看响应头发现后端确实没收到匹配路由 - Hyperf 日志里看不到对应请求日志,说明请求根本没进框架路由层
- 调试时可临时在 Nginx 配置里加
proxy_set_header X-Debug-Path $request_uri;,再查 access log 确认转发路径
必须设置 proxy_http_version 1.1 和 Connection 头支持长连接
Hyperf 默认启用协程 HTTP 服务器,依赖 HTTP/1.1 的 keepalive 保持连接复用。若 Nginx 用默认 HTTP/1.0 转发,每次请求都新建 TCP 连接,协程调度开销陡增,压测时 QPS 明显下降,且可能触发 SWOOLE_PROCESS_NUM 限制提前耗尽进程。
关键配置项只有两行,缺一不可:
proxy_http_version 1.1; proxy_set_header Connection '';
-
proxy_http_version 1.1启用长连接协议版本 -
proxy_set_header Connection ''清空客户端传来的Connection: keep-alive,避免 Nginx 错误地关闭后端连接 - 不加这两句,
ab或wrk压测时容易出现大量Connection refused或超时,尤其在高并发场景下
proxy_redirect default 是防止重定向泄露后端地址的兜底方案
Hyperf 应用内若使用 response()->redirect() 或抛出 RedirectException,底层会返回 302 + Location: http://localhost:9501/login 这类头 —— 若 Nginx 不处理,客户端将直接跳转到暴露的内部地址,失败且不安全。
最简可靠的写法就是:
proxy_redirect default;
- 它自动把后端返回的
Location头中协议、域名、端口替换为当前请求的外网信息(比如https://api.example.com) - 比手动写
proxy_redirect http://127.0.0.1:9501/ /;更健壮,适配 HTTP/HTTPS 自动切换 - 如果用了多级反向代理(如 CDN → Nginx → Hyperf),
default仍能正确还原最外层请求上下文
生产环境必须禁用 APP_DEBUG 并用 systemd 或 Supervisor 管理进程
Nginx 只负责流量接入,Hyperf 进程本身得稳定驻留。直接运行 php bin/hyperf.php start 前台启动,终端断开或 SSH 超时就会退出,不是生产行为。
推荐用 systemd(Ubuntu 20.04+/CentOS 7+):
[Unit] Description=Hyperf API Service After=network.target [Service] Type=simple User=www-data WorkingDirectory=/var/www/hyperf-app ExecStart=/usr/bin/php bin/hyperf.php start Restart=always RestartSec=3 Environment=APP_ENV=prod Environment=APP_DEBUG=false [Install] WantedBy=multi-user.target
-
APP_DEBUG=false必须通过Environment注入,不能只改.env—— systemd 不读取 .env 文件 - 检查是否生效:
systemctl show hyperf.service | grep APP_DEBUG - Supervisor 用户注意:
environment=APP_DEBUG="false"的引号不能省,否则值为空字符串,等效于 true
Hyperf 的协程模型对连接生命周期敏感,Nginx 和 PHP 进程任一端配置松散,都会放大超时、复位、内存泄漏问题。真正上线前,至少用 curl -I 和 ss -tnp | grep :9501 看连接状态,比跑通首页更重要。


















