必须用Nginx反向代理实现WSS,因Workerman无HTTP解析能力,无法处理TLS握手与WebSocket升级请求;Nginx需透传Upgrade/Connection头、启用HTTP/1.1、配置完整证书链并设置长超时。

Workerman 本身不直接处理 WSS 握手,必须用 Nginx 反向代理做 TLS 终结——这是最稳定、微信小程序唯一认的方案。 直接在 Workerman 启用 ssl transport 虽然语法上可行,但极易因证书链、SNI、HTTP Upgrade 头缺失导致握手失败,尤其在微信环境里几乎必挂。
为什么不能让 Workerman 自己监听 wss://443?
Workerman 的 ssl transport 仅负责底层 TLS 加密通道,它不解析 HTTPS 请求头,也不响应 Upgrade: websocket 协议升级。而微信小程序发起 wss 连接时,首包是标准 HTTPS GET 请求,带 Upgrade 和 Connection: upgrade 头。Workerman 没有 HTTP Server 能力,会直接丢弃或返回 400/500,连接立刻断开。
常见现象:fail net::ERR_CONNECTION_REFUSED 或控制台卡在 connecting 状态几秒后超时。
- Workerman 原生
Worker('websocket://...')不支持处理 TLS 握手 + HTTP 升级两个阶段 - 即使加了
'transport' => 'ssl',也只适用于客户端直连(如浏览器 JS new WebSocket("wss://...:8282")),且要求域名、证书、端口全部严格匹配 - 微信强制校验证书有效性(不能自签、不能局域网 IP)、SNI、完整证书链,Workerman 无法透传或补全这些
Nginx 反代配置:最小可用 wss 入口
Workerman 只监听本地明文 ws 地址,Nginx 负责 TLS 终结、协议识别与转发。这是生产环境唯一推荐方式。
关键点不是“配对”,而是“不干扰”:
- Nginx 必须透传
Upgrade和Connection头,否则 Workerman 收不到升级请求 -
proxy_http_version 1.1是硬性要求,HTTP/1.0 不支持 Upgrade -
proxy_read_timeout要设大(如86400),避免空闲连接被 Nginx 断开 - 证书路径必须是 PEM 格式完整链(
fullchain.pem,含中间证书),单独.crt文件大概率握手失败
示例配置(保存为 /usr/local/nginx/conf/vhost/your-domain.conf):
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:2346;
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_read_timeout 86400;
}
}
配置完务必执行:nginx -t && nginx -s reload
Workerman 端只需跑纯 ws 服务
Workerman 完全不用碰证书文件,也不用改 transport。它只暴露一个本地明文 WebSocket 服务,由 Nginx 代理出去变成 wss。
启动代码(start.php)示例:
<?php
require_once __DIR__ . '/Workerman/Autoloader.php';
use Workerman\Worker;
$worker = new Worker('websocket://127.0.0.1:2346');
$worker->onMessage = function($connection, $data) {
$connection->send('pong');
};
Worker::runAll();
- 监听地址必须是
127.0.0.1,禁止绑定0.0.0.0暴露到公网 - 端口随意(如
2346、8282),只要和 Nginxproxy_pass一致即可 - 不要在
$worker上设置任何 SSL 相关上下文,否则反而干扰
验证和排错重点
证书和 Nginx 配置看似生效,但微信仍连不上?90% 出在以下三处:
- 用
openssl s_client -connect your-domain.com:443 -servername your-domain.com检查证书链是否完整(输出里要有Verify return code: 0 (ok)) - 用浏览器访问
wss://your-domain.com(注意不是ws://),F12 Console 执行new WebSocket("wss://your-domain.com"),看是否触发onopen - 检查 Nginx error log(
/usr/local/nginx/logs/error.log),搜索upstream prematurely closed或no live upstreams,确认后端 Workerman 进程确实在运行且可连 - 微信开发者工具里「调试基础库」要 ≥ 2.10.0,旧版本不支持部分 TLS 1.3 特性
真正麻烦的从来不是写几行 PHP,而是让证书、Nginx、域名、防火墙、小程序 SDK 全部对齐同一套 TLS 行为——漏掉任意一环,连接就静默失败。


















