Webman生产环境必须监听127.0.0.1非特权端口(如8787),禁止0.0.0.0:80暴露;Nginx需通过upstream反向代理,配置proxy_http_version 1.1、Upgrade/Connection头以支持WebSocket,并启用keepalive与proxy_buffering off确保长连接和实时性。

Webman监听端口必须改成本地回环 + 非80/443端口
直接让Webman监听 0.0.0.0:80 或暴露公网 IP 是生产环境大忌。Nginx 反向代理的前提是 Webman 只对本机开放,否则既绕过 Nginx 的 SSL 终止、静态资源分发和安全控制,又可能被恶意直连导致请求头缺失、IP 伪造、WebSocket 升级失败等问题。
正确做法是:在 config/server.php 中将 listen 改为 '127.0.0.1:8080'(或任意非特权端口,如 8787、9501),确保外部无法绕过 Nginx 直达 Webman。
- 若用
0.0.0.0:8080,需额外在防火墙或安全组中封禁该端口对外访问 - 多实例部署时,每个 Webman 实例必须使用不同端口(如
8080、8081、8082),避免端口冲突 - Windows 下不支持
pcntl,start.php start -d会静默失败,务必用 Linux 生产环境
Nginx upstream 配置 WebSocket 和 HTTP 共存的要点
Webman 常同时提供 HTTP API 和 WebSocket 服务(如聊天、实时通知),但 Nginx 默认不识别 WebSocket 协议升级,直接 proxy_pass 会导致 502 或连接立即关闭。
关键不是写两套 server 块,而是在同一 location 内兼容两者:检测 $http_upgrade 头决定是否走 WebSocket 流程,其余走普通 HTTP。配置必须包含以下四行:
立即学习“PHP免费学习笔记(深入)”;
proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host;
完整示例(假设 Webman 启动在 127.0.0.1:8080):
upstream webman_cluster {
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
keepalive 32;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://webman_cluster;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffering off;
}
}
-
keepalive 32必须加在 upstream 块里,否则长连接复用失效,WebSocket 易断连 -
proxy_buffering off对实时性要求高的接口(如 SSE、流式响应)能减少延迟 - 不要在 location 中写
proxy_redirect,Webman 返回的重定向 Location 已含完整 URL,强行改写反而出错
多机器集群下 session 和缓存必须外置
Webman 默认使用文件存储 session,单机没问题;一旦用 Nginx upstream 分发到多台 Webman 服务器,用户刷新页面就可能跳到另一台机器,session 丢失,登录态中断。
必须把 session 和高频缓存统一交给外部服务,且不能依赖本地磁盘:
- session 存 Redis:修改
config/session.php中handler为'redis',并确认config/redis.php指向集群共用的 Redis 实例(非127.0.0.1) - 配置中心化:所有 Webman 实例共用同一份
.env(通过挂载卷或配置管理工具同步),尤其APP_KEY必须一致,否则加密/解密 session 失败 - 避免用 APCu 或 file 缓存做跨实例共享,它们只在单进程内存或单机文件系统生效
- 数据库连接池(如
config/database.php中的pool配置)建议设为10~20,过高易占满 DB 连接数
Docker 部署时 network 和 healthcheck 容易被忽略
用 docker run 或 Docker Compose 启动 Webman 容器时,如果没显式指定网络模式,容器默认用 bridge 网络,127.0.0.1 在容器内指向自己,而非宿主机上的 Nginx —— 导致 Nginx proxy_pass http://127.0.0.1:8080 转发失败。
正确方式是让 Webman 容器与 Nginx 容器处于同一自定义网络,并用服务名通信:
version: '3.8'
services:
nginx:
image: nginx:alpine
ports: ["80:80"]
volumes: [./nginx.conf:/etc/nginx/conf.d/default.conf]
depends_on: [webman1, webman2]
webman1:
image: ghcr.io/tinywan/docker-php-webman:8.2.11
environment: [APP_ENV=production]
expose: ["8080"]
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 5s
retries: 3
webman2:
image: ghcr.io/tinywan/docker-php-webman:8.2.11
environment: [APP_ENV=production]
expose: ["8080"]
healthcheck: [...]
- Nginx 配置中的
proxy_pass应写成http://webman1:8080和http://webman2:8080,而不是127.0.0.1 -
healthcheck不只是“好看”,Kubernetes 或 Swarm 编排时依赖它判断实例是否就绪,避免流量打到未启动完成的容器 - 镜像标签别用
latest,生产环境必须锁定具体版本(如8.2.11),防止基础镜像更新引入 PHP 行为变更



















