AWS EC2环境下PHP相关Socket.io无法正常工作问题排查
解决EC2上Socket.io/kriss-webMsgSender连接异常的实战方案
刚看到你的问题,我之前在AWS EC2部署Socket相关服务时也踩过几乎一模一样的坑,给你梳理几个排查和解决的方向:
1. 先确认EC2实例内部的服务可用性
别先急着查外部网络,先在EC2实例的命令行里测试本地连通性,排除服务本身的问题:
# 用telnet测试端口是否能连通 telnet 127.0.0.1 2120 # 或者直接请求Socket.io的polling路径 curl "http://localhost:2120/socket.io/?EIO=3&transport=polling&t=NQpMyRI"
如果本地请求都失败,那先去看workerman或webMsgSender的启动日志,大概率是服务没正常启动或者端口被占用了;如果本地能通,那问题肯定出在外部到EC2的网络链路或者配置上。
2. 把EC2的安全组+网络ACL+本地防火墙查个遍
这三个是最容易踩坑的地方,别只看安全组:
- 安全组:你说已经加了入站规则,但一定要确认规则的源地址是0.0.0.0/0(或者你的客户端IP范围),端口是2120,协议选TCP(Socket.io的polling和websocket都是基于TCP的)。另外出站规则别限制太死,至少允许所有TCP出站流量。
- 网络ACL:如果你的EC2在VPC里,网络ACL是双向的!要同时配置入站和出站规则,允许2120端口的TCP流量,源和目标都设成0.0.0.0/0(对应公网访问的场景)。
- 本地防火墙(Ubuntu的ufw/iptables):Ubuntu默认可能开启ufw,很多人会忽略这个!执行下面的命令检查:
# 查看ufw状态 sudo ufw status # 如果发现2120端口没放行,添加规则 sudo ufw allow 2120/tcp # 用iptables再确认一遍 sudo iptables -L -n | grep 2120
3. 针对kriss\webMsgSender的配置调整
看了你贴的配置,有几个细节要注意:
use kriss\webMsgSender\WebMsgSender; return [ 'components' => [ // others WebMsgSender::COMPONENT_NAME => [ 'class' => WebMsgSender::class, 'pushApiClientHost' => '0.0.0.0', 'logCategory' => 'webMsgSender', ], ], ];
- 确认
pushApiClientPort参数:如果没显式设置,组件可能用的是默认端口(比如9501?),要确保这个端口和你安全组里开放的2120一致! - 适配HTTPS场景:你的前端是用HTTPS访问的(
https://mydoamin.com),浏览器会限制HTTPS页面访问HTTP的Socket服务,直接访问端口会出现ERR_CONNECTION_RESET或跨域问题。最好的解决办法是用Nginx做反向代理,把Socket请求转发到本地服务:
location /socket.io/ { proxy_pass http://localhost:2120; 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; # 如果有跨域需求,再加下面的配置 add_header Access-Control-Allow-Origin "https://mydoamin.com"; add_header Access-Control-Allow-Credentials true; }
配置完后,前端就可以用wss://mydoamin.com/socket.io来连接,不用直接加端口号,还能规避HTTPS和HTTP混合的限制。
4. 检查域名解析和EC2公网IP
确认你的mydoamin.com解析的是EC2的公网IP/弹性IP,而不是私网IP。如果用了弹性IP,要确保已经绑定到对应的EC2实例上。
5. 排查跨域配置
本地环境可能因为是localhost不会有跨域问题,但生产环境域名不同就会触发。如果用原生Socket.io,要在服务端配置跨域允许:
const io = require('socket.io')(server, { cors: { origin: "https://mydoamin.com", methods: ["GET", "POST"] } });
如果是kriss\webMsgSender,看看组件有没有提供跨域配置项,或者直接用上面Nginx的配置来处理跨域。
内容的提问来源于stack exchange,提问作者Dev 1
相关产品推荐
相关产品推荐

