Websocket 在使用 AWS ELB 的连接节点服务器空闲 60 秒后关闭
Websocket closing after 60 seconds of being idle while connection node server using AWS ELB
我在 EC2 实例上有一个节点服务器 运行,客户端也在同一个 EC2 实例上 运行,客户端打开 websocket 连接与节点服务器通信,它在 QA 和 Dev AWS 环境中工作但是在 prod 环境中闲置 60 秒后,相同的网络连接正在关闭,我是 运行 aws 环境中 ELB 后面的客户端和节点服务器。
客户代码:
ws = new WebSocket('ws://localhost:8443');
ws.onclose = function () {
console.log("Websocket connection has been closed.");
clientObj.emit('LogoffSuccess', 'LogoffSuccessfully');
};
ws.onerror=function(event)
{
console.log(event.data);
};
ws.addEventListener('open', function (event) {
console.log('Websocket connection has been opened');
ws.send(JSON.stringify(loginCreds));
});
节点服务器代码如下:
const wss = new WebSocket.Server({ server: app });
const clients = {};
const idMap = {};
wss.on(`connection`, ws => {
const headers = ws.upgradeReq.headers;
const host = headers.host;
const key = ws.upgradeReq.headers[`sec-websocket-key`];
ctiServer.on(`responseMessage`, message => {
clients[message.AgentId].send(JSON.stringify(message));
});
ws.on(`message`, message => {
log.info(`Message received. Host: ${host}, Msg: ${message}`);
if (JSON.parse(message).EventName === `Login`) {
clients[JSON.parse(message).AgentId] = ws;
idMap[key] = JSON.parse(message).AgentId;
}
ctiServer.processIncomingRequest(message);
});
ws.on(`close`, () => {
log.info(`Connection closed. Host: ${host}`);
const message = {
EventName: `Logoff`,
AgentId: idMap[key],
EventData: {}
};
});
});
PING!
编写 ping 实现(或 nil
消息实现)...
...否则 AWS 代理(可能是 nginx)将在一段时间不活动后关闭连接(在您的情况下为 60 秒,但在不同的系统上会有所不同)。
By default, Elastic Load Balancing sets the idle timeout value to 60 seconds. Therefore, if the target doesn't send some data at least every 60 seconds while the request is in flight, the load balancer can close the front-end connection. To ensure that lengthy operations such as file uploads have time to complete, send at least 1 byte of data before each idle timeout period elapses, and increase the length of the idle timeout period as needed.
请注意,定期发送流量以保持连接有效最符合您的利益。您可以在 Application Load Balancer 中将空闲超时设置为最多 4000 秒,但您会发现有状态的中间网络基础设施(防火墙、NAT 设备)往往会在连接实际空闲这么长时间之前重置连接。
你使用 NGINX 吗?他们的请求在 60 秒后超时。
您可以在 NGINX 配置文件中为您的 websockets 特定位置延长超时时间。
在您的情况下,将超时延长到一个小时可能看起来像这样:
...
location / {
...
proxy_pass http://127.0.0.1:8443;
...
proxy_read_timeout 3600;
proxy_send_timeout 3600;
...
}
另请参阅此网站以获取更多信息:
https://ubiq.co/tech-blog/increase-request-timeout-nginx/
https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout
https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_send_timeout
我在 EC2 实例上有一个节点服务器 运行,客户端也在同一个 EC2 实例上 运行,客户端打开 websocket 连接与节点服务器通信,它在 QA 和 Dev AWS 环境中工作但是在 prod 环境中闲置 60 秒后,相同的网络连接正在关闭,我是 运行 aws 环境中 ELB 后面的客户端和节点服务器。
客户代码:
ws = new WebSocket('ws://localhost:8443');
ws.onclose = function () {
console.log("Websocket connection has been closed.");
clientObj.emit('LogoffSuccess', 'LogoffSuccessfully');
};
ws.onerror=function(event)
{
console.log(event.data);
};
ws.addEventListener('open', function (event) {
console.log('Websocket connection has been opened');
ws.send(JSON.stringify(loginCreds));
});
节点服务器代码如下:
const wss = new WebSocket.Server({ server: app });
const clients = {};
const idMap = {};
wss.on(`connection`, ws => {
const headers = ws.upgradeReq.headers;
const host = headers.host;
const key = ws.upgradeReq.headers[`sec-websocket-key`];
ctiServer.on(`responseMessage`, message => {
clients[message.AgentId].send(JSON.stringify(message));
});
ws.on(`message`, message => {
log.info(`Message received. Host: ${host}, Msg: ${message}`);
if (JSON.parse(message).EventName === `Login`) {
clients[JSON.parse(message).AgentId] = ws;
idMap[key] = JSON.parse(message).AgentId;
}
ctiServer.processIncomingRequest(message);
});
ws.on(`close`, () => {
log.info(`Connection closed. Host: ${host}`);
const message = {
EventName: `Logoff`,
AgentId: idMap[key],
EventData: {}
};
});
});
PING!
编写 ping 实现(或 nil
消息实现)...
...否则 AWS 代理(可能是 nginx)将在一段时间不活动后关闭连接(在您的情况下为 60 秒,但在不同的系统上会有所不同)。
By default, Elastic Load Balancing sets the idle timeout value to 60 seconds. Therefore, if the target doesn't send some data at least every 60 seconds while the request is in flight, the load balancer can close the front-end connection. To ensure that lengthy operations such as file uploads have time to complete, send at least 1 byte of data before each idle timeout period elapses, and increase the length of the idle timeout period as needed.
请注意,定期发送流量以保持连接有效最符合您的利益。您可以在 Application Load Balancer 中将空闲超时设置为最多 4000 秒,但您会发现有状态的中间网络基础设施(防火墙、NAT 设备)往往会在连接实际空闲这么长时间之前重置连接。
你使用 NGINX 吗?他们的请求在 60 秒后超时。
您可以在 NGINX 配置文件中为您的 websockets 特定位置延长超时时间。
在您的情况下,将超时延长到一个小时可能看起来像这样:
...
location / {
...
proxy_pass http://127.0.0.1:8443;
...
proxy_read_timeout 3600;
proxy_send_timeout 3600;
...
}
另请参阅此网站以获取更多信息:
https://ubiq.co/tech-blog/increase-request-timeout-nginx/
https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout
https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_send_timeout