为什么 AWS ALB 在使用 Socket.io 时会断开连接
Why would AWS ALB disconnect when using Socket.io
我正在尝试让 ALB/Node.js/socket.io 解决方案以最简单的形式运行,但我 运行 遇到了握手断开连接的问题。目前,我有意只使用 TargetGroup 中的一个节点来暂时消除与节点切换和会话粘性相关的变量。
当通过我的 NAT 实例直接连接到节点时,它工作正常。断开连接仅在通过 ALB 时发生。
这是我设置的:
- 带有侦听器 HTTP 80 -> 8081(无 SSL)的 ALB
- 2 个可用区,均具有互联网路由(根据 ALB 的要求)
- 其中一个 AZ 中的一个 socket.io EC2 节点
- /socket.io/* 到 socket.io 目标组的路径模式(其中包含我的一个节点)
- 默认模式也是socket.io目标群体
- 已启用粘性(应该不需要一个节点,但无论如何都需要)
这是我在 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 中负载均衡器的空闲超时
希望这样可以防止超时问题!
我正在尝试让 ALB/Node.js/socket.io 解决方案以最简单的形式运行,但我 运行 遇到了握手断开连接的问题。目前,我有意只使用 TargetGroup 中的一个节点来暂时消除与节点切换和会话粘性相关的变量。
当通过我的 NAT 实例直接连接到节点时,它工作正常。断开连接仅在通过 ALB 时发生。
这是我设置的:
- 带有侦听器 HTTP 80 -> 8081(无 SSL)的 ALB
- 2 个可用区,均具有互联网路由(根据 ALB 的要求)
- 其中一个 AZ 中的一个 socket.io EC2 节点
- /socket.io/* 到 socket.io 目标组的路径模式(其中包含我的一个节点)
- 默认模式也是socket.io目标群体
- 已启用粘性(应该不需要一个节点,但无论如何都需要)
这是我在 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 中负载均衡器的空闲超时
希望这样可以防止超时问题!