webman在k8s中需正确配置才能实现有效水平扩展:必须通过环境变量注入端口、禁用多进程干扰、配置合理的健康探针、结合自定义指标(如请求量或连接数)驱动hpa,并按状态存储方式决定是否启用sessionaffinity。

Webman 是基于 Swoole 的高性能 PHP 框架,常用于长连接、高并发场景。它本身是常驻内存的进程模型,不能像传统 FPM 那样靠简单复制 Pod 就自动负载均衡——直接套用标准 Deployment 扩容会出问题:多个 Webman 进程监听同一端口(如 80),在同一个 Pod 内会冲突;跨 Pod 又没内置服务发现和连接分发逻辑。
必须明确一点:K8s 的水平扩展对 Webman 有效,但前提是它被正确封装为无状态、端口隔离、可被 Service 路由的单元。否则扩容只是“假扩”,流量全打到一个实例上,或直接启动失败。
确保 Webman 容器镜像支持多副本独立运行
Webman 默认启动时绑定 0.0.0.0:80,这在单容器没问题,但在 K8s 多副本下,每个 Pod 必须能独立监听自己的端口(K8s 会做网络隔离)。你需要确认:
- 镜像中
start.php或启动脚本不硬编码端口,而是通过环境变量注入,例如:php start.php start -d -p ${WEBMAN_PORT:-80} - 构建镜像时未开启
--daemon以外的全局监听控制(比如没用swoole_server->addProcess()启动额外主控进程干扰生命周期) - 容器内没有使用
supervisord或多进程管理器——K8s 要求主进程是前台、可被 SIGTERM 正确终止
常见错误现象:CrashLoopBackOff,日志显示 Address already in use 或 port 80 is occupied,本质是多个 worker 尝试绑定同一地址,或镜像启动方式不兼容容器 init 流程。
Deployment 必须配置 readinessProbe 和 livenessProbe
Webman 启动较慢(尤其带 ORM 或 Redis 连接池初始化),且长连接场景下健康检查不能只看端口通不通。
-
readinessProbe应指向一个轻量 HTTP 接口(如/health),返回200表示已加载完路由、连接池就绪 -
livenessProbe建议用 TCP + 自定义脚本结合,避免仅靠 HTTP 导致长连接阻塞时误杀 - probe 的
initialDelaySeconds至少设为15,timeoutSeconds不低于5
示例片段:
readinessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 20
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 30
periodSeconds: 30
忽略这点会导致新 Pod 还没 ready 就被 Service 加入 endpoint,请求 502/超时;或因长连接阻塞 probe 而反复重启。
HPA 扩容不能只依赖 CPU,优先用自定义指标
Webman 是常驻进程,CPU 使用率在空闲时极低,但实际连接数(worker_num × max_request)或 QPS 上升时,CPU 可能还没明显变化。单纯设 cpu.targetAverageUtilization: 70 容易扩容滞后甚至失效。
你得接入 Prometheus + prometheus-adapter,暴露以下任一指标供 HPA 使用:
-
webman_http_requests_total(每秒请求数) -
webman_worker_connections(当前活跃连接数) - 自定义 exporter 报告的
webman_queue_length(任务队列积压)
然后写 HPA spec:
metrics:
- type: Pods
pods:
metric:
name: webman_http_requests_total
target:
type: AverageValue
averageValue: 1000
注意:Metrics Server 默认不采集应用指标,只提供 CPU/memory。跳过这步,kubectl autoscale 创建的 HPA 会一直显示 unknown 状态。
Service 类型和会话保持要按需取舍
Webman 是否需要 sessionAffinity: ClientIP,取决于你的业务:
- 如果用了
Redis存 session,或所有状态外置,不要开亲和性——它会破坏负载均衡,导致部分 Pod 过载 - 如果用了本地
file或arraysession,又没改造成共享存储,那必须开,但这是反模式,应优先重构
另外,type: LoadBalancer 在云厂商环境可用,但本地 minikube 或裸机需搭配 metalLB;若只是调试,type: NodePort 更快验证。
真正容易被忽略的是:Webman 的 worker_num 配置和 K8s 的 replicas 是两层缩放——前者管单个 Pod 内并发能力,后者管集群维度副本数。别把 worker_num 设得过大(比如 100),再配 10 个副本,结果总连接数远超后端 DB/Redis 承载力。











