Webman跑短信中继需自控协议解析与连接复用:SMPP须用swoole_tcp_server手动监听,HTTP接入禁用CSRF/session,路由规则存Redis+APCu缓存,消息必须落redis_stream或可靠中间件,Nginx需调大body_size、关闭buffering并透传header。

Webman 要跑短信中继,得先扛住并发连接和协议解析压力
Webman 本身不是为短信协议(如 SMPP、HTTP API 接入)设计的,但它的常驻内存 + 协程模型确实适合做高吞吐中继网关——前提是别把它当“黑盒 HTTP 框架”用。你得把协议解析、连接复用、路由分发这些事全拎出来自己控,否则一上来就崩在 onMessage 里查数据库或调第三方接口。
常见错误现象:Connection reset by peer 频发、SMPP bind 失败率高、HTTP 短信回调积压超时、单机 QPS 卡在 200 以下。
- SMPP 连接必须用
swoole_tcp_server或swoole_socket手动监听,Webman 的 HTTP Worker 对 SMPP 完全无效 - HTTP 短信接入端点(如
/sms/callback)要禁用 CSRF 和 session,避免协程间状态污染 - 每个运营商通道建议独占一个 Worker 进程(通过
worker_num分配),避免 TCP 粘包/拆包互相干扰 - SMPP PDU 解析不能依赖第三方库的同步阻塞实现;推荐用
php-smpp的无锁 buffer + 协程 parser,或手写状态机跳过冗余字段
短信路由与通道选择不能靠 if-else 写死
企业级中继系统里,“按号段选通道”“按失败率降级”“按计费类型分流”都是常态。硬编码路由逻辑会迅速变成维护噩梦,且无法热更新。
使用场景:某省移动号段走 A 通道,但 A 通道连续 5 分钟失败率 > 15%,自动切到 B;VIP 用户强制走低延迟专线。
- 路由规则存 Redis Hash(
route:rules),用HGETALL加本地 APCu 缓存,TTL 设 60 秒,避免每次发都查 Redis - 通道健康度用 Redis Sorted Set 维护:
channel:health:a存 timestamp-score,每成功一次 ZADD + time(), 失败则 ZADD + 0,ZREMRANGEBYSCORE 清理过期项 - 路由决策放在独立协程里,不卡主事件循环;输入是
$phone和$priority,输出是channel_id和timeout_ms - 禁用全局
switch($channel),改用$channels[$id]->send($pdu),通道实例提前初始化好连接池
消息可靠性不能依赖 Webman 内存队列
Client::send() 是内存缓冲,断电或 reload 就丢——拿它转发短信,等于把用户验证码扔进 /dev/null。生产环境必须落盘或进可靠中间件。
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
性能影响:MySQL 直写 INSERT INTO sms_out 在 500+ TPS 下会触发连接池耗尽;Redis List LPUSH + RPOP 在万级并发下易成瓶颈。
- 发短信前先写
redis_stream(key=sms:pending),用XADD带msg_id和channel_hint,服务端消费端用XREADGROUP拉取 - 每条短信记录必须带唯一
request_id(客户端传入或服务端生成),用于幂等去重和状态回溯 - 失败重试走死信队列:消费端
try/catch后,失败消息XADD sms:dlq并打上retry_count字段,后台定时任务捞出重投 - 禁止在
onMessage里做file_put_contents记日志,改用Worker::$log->info()或异步Logger::push()
Nginx 反向代理对短信 HTTP 接入必须做特殊配置
普通 Web 应用的 Nginx 配置直接套用到短信接口上,90% 会出现 413 Request Entity Too Large、502 Bad Gateway 或请求头被截断。
典型问题:运营商回调带 base64 图片附件、长 URL 参数、非标准 Content-Type(如 application/x-www-form-urlencoded; charset=GBK)。
- 在 location 块里加
client_max_body_size 10M,默认 1M 不够传彩信模板 - 关闭
proxy_buffering on,设为off,否则大响应体卡在 Nginx 缓冲区,Webman 已 send 但客户端收不到 - 透传所有 header:
proxy_pass_request_headers on,并显式放行Content-Encoding、X-SMS-Operator等自定义头 - 超时必须拉长:
proxy_read_timeout 300(短信网关响应慢)、proxy_connect_timeout 60(避免 DNS 或 TLS 握手被掐)
最易被忽略的是字符集处理——GB2312 编码的短信内容若没在 Nginx 层声明 charset GBK,Webman 收到的就是乱码,后续签名验签全错。


















