为什么 AWS ALB 在使用 Socket.io 时会断开连接

Why would AWS ALB disconnect when using Socket.io

我正在尝试让 ALB/Node.js/socket.io 解决方案以最简单的形式运行,但我 运行 遇到了握手断开连接的问题。目前,我有意只使用 TargetGroup 中的一个节点来暂时消除与节点切换和会话粘性相关的变量。

当通过我的 NAT 实例直接连接到节点时,它工作正常。断开连接仅在通过 ALB 时发生。

这是我设置的:

这是我在 socket.io 节点客户端中看到的:

Thu, 22 Dec 2016 20:59:26 GMT socket.io-client:manager opening ws://52.72.198.58
Thu, 22 Dec 2016 20:59:26 GMT engine.io-client:socket creating transport "websocket"
Thu, 22 Dec 2016 20:59:26 GMT engine.io-client:socket setting transport websocket
Thu, 22 Dec 2016 20:59:26 GMT socket.io-client:manager connect attempt will timeout after 20000
Thu, 22 Dec 2016 20:59:26 GMT engine.io-client:socket socket close with reason: "transport close"

这是我在 socket.io 节点服务器上看到的:

Thu, 22 Dec 2016 20:59:26 GMT socket.io:socket joined room U_qmSv_7gvP_JOFsAAAL
Thu, 22 Dec 2016 20:59:26 GMT socket.io:client client close with reason transport close
Thu, 22 Dec 2016 20:59:26 GMT socket.io:socket closing socket - reason transport close

当我通过我的 NAT 连接到同一个 socket.io ec2 节点时,一切正常,没有传输关闭。

所以 ALB 在握手成功期间以某种方式立即关闭连接。

由于它通过 NAT 工作,我认为 socket.io 节点和客户端都可以。由于我在节点中看到 DEBUG 条目,我知道 ALB 能够正常到达 socket.io 节点。由于我只有一个 socket.io 节点,因此会话和粘性应该没有问题。

什么可能导致使用 ALB 时立即断开连接?

EDIT :我还发现,如果向 ELB 发出请求的 socket.io 客户端在 EC2 节点上,那么它就可以工作。这意味着客户端和 ELB 之间的网络路径中存在某些内容。除了客户端在 EC2 上之外,我还没有找到这种方法有效的情况。它通过 NAT 在任何地方工作,而不是通过 ELB。

经过大量试验和错误后,我能够确定这是由于 ALB/ELB 正在侦听的端口在我的情况下的特定端口范围 (80-83)。当握手的 HTTP 部分工作时,第二个 TCP 升级阶段断开连接。

这个端口范围相关的VPC没有限制,所以问题出在我的客户端和ELB之间的网络上。

总而言之,问题不在 AWS 中或我如何设置资源,而是在 AWS 之外的其他地方。如果我找到确切原因,我会 post 回复此答案的评论。

socket = io.connect("https://mywebsite/myroom",{'reconnect':true});

初始化时增加 HeartbeatTimeout 和 closeTimeout

socket.on('connect', function(){
    socket.socket.heartbeatTimeout = 500000;
    socket.socket.closeTimeout = 500000;
    socket.on('disconnect', function() {
        socketConnectTimeInterval = setInterval(function () {
        socket.socket.reconnect();
            if(socket.socket.connected) {
                clearInterval(socketConnectTimeInterval);
                 console.log('reconnected');
                 location.reload();
            }
        }, 0);
    });
});

同时增加 AWS 中负载均衡器的空闲超时

希望这样可以防止超时问题!