生产服务器Meteor应用WebSocket连接404错误排查求助
问题描述
部署在生产服务器上的Meteor应用HTTP/HTTPS服务正常,但React Native客户端通过Meteor RN库连接WebSocket失败。使用wscat、curl测试wss://example.com/websocket返回404,直接请求后端http://127.0.0.1:10013/websocket也报404。NGINX日志记录了/websocket路径的404错误,但Meteor/pm2无对应请求日志,说明请求未到达Meteor服务。
环境详情
- Meteor版本:2.12
- Node.js版本:14.21.3
- 操作系统:Ubuntu 20.04
- 部署方式:
meteor build打包部署 - 反向代理:NGINX
可用功能
- 常规HTTP请求正常,
https://example.com应用加载正常 - SockJS回退功能可用(NGINX日志可见)
已尝试操作
- 配置环境变量启用WebSocket:
{ "DISABLE_WEBSOCKETS": false, "ROOT_URL": "https://example.com", "PORT": 10013, "MONGO_URL": "mongodb://localhost:27017/myapp" }
- 重新安装Meteor bundle依赖:
cd programs/server npm install --force
- 验证NGINX配置(
nginx -t)并重启服务 - 使用curl和wscat测试均返回404
当前NGINX配置
server { server_name example.com; location / { proxy_pass http://127.0.0.1:10013; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /websocket { proxy_pass http://127.0.0.1:10013/websocket; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; } listen 443 ssl; ssl_certificate /route/to/certificate/fullchain.pem; # managed by Certbot ssl_certificate_key /route/to/certificate/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot } server { if ($host = example.com) { return 307 https://$host$request_uri; } # managed by Certbot server_name example.com; listen 80; return 404; # managed by Certbot }
解决方案
你的NGINX配置存在两个关键问题导致WebSocket请求无法正确转发:
1. location /websocket的proxy_pass路径末尾多了/websocket
Meteor的WebSocket端点是/websocket,当配置proxy_pass http://127.0.0.1:10013/websocket时,NGINX会把客户端请求的/websocket重写为/websocket/websocket,导致Meteor无法识别该路径,返回404。
修正方式:移除proxy_pass末尾的/websocket,并添加超时配置增强稳定性:
location /websocket { proxy_pass http://127.0.0.1:10013; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_read_timeout 300s; proxy_send_timeout 300s; proxy_set_header X-Forwarded-Proto $scheme; }
2. 80端口的HTTP跳转配置拦截WebSocket升级请求
当前80端口的配置除Certbot规则外直接返回404,需确保所有HTTP请求(包括WebSocket升级请求)都重定向到HTTPS。修改80端口的server块:
server { server_name example.com; listen 80; # 统一重定向所有HTTP请求到HTTPS return 301 https://$host$request_uri; # 保留Certbot的ACME挑战路径(用于证书续期) location ~ /.well-known/acme-challenge/ { root /var/www/certbot; allow all; } }
额外验证步骤:确认Meteor服务正在监听10013端口,且本地防火墙未拦截该端口:
netstat -tulpn | grep 10013
完成配置修改后,重启NGINX和Meteor服务,再用wscat测试连接:
wscat -c wss://example.com/websocket
若连接成功,会显示connected (press CTRL+C to quit),此时React Native客户端的WebSocket连接也应恢复正常。
内容的提问来源于stack exchange,提问作者Mal d'Aurore

