AWS ALB后部署Node.js+Socket.io服务出现WebSocket连接异常
可能触发异常的原因
- WebSocket请求未携带X-Pass-To请求头
你Nginx配置中判断如果X-Pass-To请求头为空,会直接返回200状态码,而WebSocket握手要求返回101 Switching Protocols状态码才能完成协议切换。如果客户端发起WebSocket连接时没有带上X-Pass-To头,握手会直接失败,Socket.io会自动降级到长轮询模式,也就会出现大量重复的XHR请求。 - AWS ALB过滤了自定义请求头
AWS ALB默认会丢弃名称包含下划线的请求头,如果你客户端传递的是带下划线的X_Pass_To而非中划线的X-Pass-To,请求头会在ALB层就被丢弃,最终到Nginx时为空,触发上述返回200的逻辑。另外需要检查ALB的安全组、WAF规则是否拦截了WebSocket相关的Upgrade、Connection请求头。 - Nginx未正确传递代理相关头信息
你当前配置缺少Socket.io握手需要的源站协议信息,需在location块补充以下配置:
ALB做了SSL卸载,到Nginx是HTTP协议,Socket.io需要通过proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Port $server_port;X-Forwarded-Proto识别原始请求是HTTPS(wss),否则会出现跨域或握手校验失败。 - ALB闲置超时时间过短
AWS ALB默认的闲置超时时间是60秒,远低于你Nginx配置的86400秒超时,若WebSocket连接超过60秒没有数据传输,ALB会主动断开连接,导致WebSocket连接异常中断。你需要将ALB的闲置超时调整到和Nginx一致的时长。 - Socket.io服务端未配置信任代理
Node.js的Socket.io服务端需要开启trust proxy配置,才能正确识别从Nginx/ALB传递过来的代理请求,否则会拒绝握手请求。参考配置:const io = require('socket.io')(server, { cors: { origin: "*" }, transports: ['websocket', 'polling'], trustProxy: true }); - CORS预检逻辑配置不完善
你当前的配置没有限定仅处理OPTIONS请求,所有未携带X-Pass-To头的请求都会直接返回200,包括WebSocket的GET类型握手请求,进一步提升了握手失败的概率。建议将if条件调整为:if ($request_method = OPTIONS) { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Headers 'X-Pass-To,User-Agent,Content-Type'; return 200; }
内容的提问来源于stack exchange,提问作者Georgi Yovchev
相关产品推荐
相关产品推荐

