Гнездо NodeJS.io: многие соединения в состоянии CLOSE WAIT и Fin WAIT2 без выпуска
я использовал ubuntu (12.04) + nodejs (v0.10.22) + розетка.io (v0.9.14) передавать сообщения.
есть ~300 одновременных подключений. Через несколько часов (около 1 или 2 часов выше, он не появляется сразу), некоторые соединения будут постоянными в состоянии close_wait состояние или FIN_WAIT2.
и эти не-мертвые связи растут линейно со временем. Пользователям будет трудно подключить сервер сокетов, когда число соединений достигнет предела (По умолчанию 1024) , если некоторые соединения, как правило, освобождены.
ниже было состояние подключения к службе сокета, работающее около 3 часов.
netstat -anl | grep <PORT_OF_NODE_PROCESS> | awk '/^tcp/ {t[$NF]++}END{for(state in t){print state, t[state]} }'
FIN_WAIT2 23
LISTEN 1
CLOSE_WAIT 27
TIME_WAIT 12
ESTABLISHED 333
FIN_WAIT1 12
Вероятно, Решения
1. Нажмите JS файл в регулярные периоды
используя Пакет Nodemon чтобы запустить JS-файл, при изменении последнего измененного времени файла nodemon перезапустит службу и освободит все предыдущие неработающие соединения (CLOSEWAIT или FINWAIT2)
2. Увеличить лимит соединений
sudo vim /etc/security/limits.conf
* soft nofile 1024
* hard nofile 2048
root soft nofile 4096
root hard nofile 8192
user1 soft nofile 2048
user1 hard nofile 2048
постарайтесь, чтобы соединения трудно достичь предела.
3. Уменьшить время ожидания keep-alive
пусть операционная система автоматически закрывает соединения за короткое время, но я еще не пробовал.
вопрос
Я нашел некоторое, вероятно, решение для устранения проблемы. Но вышеуказанные решения не были действительно решены постоянные связи с государством close_wait состояние или FIN_WAIT2 проблема. Я мог бы найти, что это результат сервера (close_wait состояние) или клиенты (FIN_WAIT2) неправильно закрывает соединения. Я думаю, сокет.io принудительно закроет это неправильное соединение после некоторого тайм-аута. Но, похоже, это работает неправильно.
Я пытаюсь снова появиться состояние close_wait состояние или FIN_WAIT2 проблема в моей тестовой среде. Но это никогда не проявится. ситуация с подключением.
- после подключения сервера сокетов и отключения сети
- подключить сервер сокетов в течение длительного времени
Я нашел, что кто-то задал связанный вопрос раньше (многие устаревшие соединения в состоянии CLOSE_WAIT и FIN_WAIT2), но все еще не может найти решение. Кто-нибудь знает как решить эту проблему??
спасибо
3 ответов
Я пытаюсь использовать несколько соединений для подключения сервера сокетов одновременно, я обнаружил, что некоторые клиентские сокеты будут использовать то же самое ИДЕНТИФИКАТОР СОКЕТА(получить от xhr, и это будет выглядеть как nmXTMmCGNQp4EncrfHqj) для установления соединения. Я закрываю браузер, когда все соединения установлены, и это вызовет много соединений CLOSE_WAIT без выпуска. Несколько соединений закроются (база по количеству уникальный идентификатор сокета, которые были сгенерированный.) Потому что сервер установит соединение TCP / IP от ИДЕНТИФИКАТОР СОКЕТА. Но если ... --4-->ИДЕНТИФИКАТОР СОКЕТА соединения уже существуют в пуле соединений, это соединение не будет храниться в пуле соединений. Поэтому, когда клиент отправляет пакет FIN, чтобы попытаться закрыть соединение, но не существует в пуле соединений с сервером. Сервер всегда не будет отправлять пакет ACK для подготовки тесного соединения. Таким образом, эти соединения останутся в close_wait состояние государство и без освобождать.
var host = 'http://socket.server/';
var sockets = [];
for(var i=0;i<200;i++){
var socket = io.connect(host,{"force new connection":true});
sockets.push(socket);
socket.on("message",function(message){
console.log(message);
});
socket.on("disconnect",function(){
console.log("disconnect");
});
}
исправить lib\manager.js строке 670.
не устанавливать TCP / IP соединение из ИДЕНТИФИКАТОР СОКЕТА, когда ИДЕНТИФИКАТОР СОКЕТА соединения уже существуют в пуле соединений.
см. также: https://github.com/kejyun/socket.io/commit/8d6c02a477d365f019530b4ec992420dfb90eb09
if (!this.connected[data.id]) {
if (transport.open) {
if (this.closed[data.id] && this.closed[data.id].length) {
transport.payload(this.closed[data.id]);
this.closed[data.id] = [];
}
this.onOpen(data.id);
this.store.publish('open', data.id);
this.transports[data.id] = transport;
}
this.onConnect(data.id);
this.store.publish('connect', data.id);
//....etc
}
}
ниже было состояние подключения к службе сокета, работающее около 6 несколько часов.
netstat -anl | grep <PORT_OF_NODE_PROCESS> | awk '/^tcp/ {t[$NF]++}END{for(state in t){print state, t[state]} }'
FIN_WAIT2 37
LISTEN 1
TIME_WAIT 13
ESTABLISHED 295
FIN_WAIT1 20
вышеуказанное решение может решить CLOSE_WAIT, но не решает FIN_WAIT2. Последнее обсуждение здесь (https://github.com/LearnBoost/socket.io/issues/1380) предлагает возможные альтернативные решения. Это обсуждение также указывает на то, что проблема находится в node.js сам по себе, а не сокет.Ио.
если вы используете уроженца cluster
module и spawn workers, обратите внимание, что если ваш рабочий процесс будет убит насильственно с подключенными к нему клиентами (т. е. из-за низкой системной памяти), он оставит позади CLOSE_WAIT
розетки которые будут засорять системные ресурсы бесконечно.
обходной путь-убить ваш основной узел.процесс js, как только один из ваших работников будет прекращен ОС. Как только главный узел.процесс js убит, система уничтожит все сокеты в CLOSE_WAIT
принадлежащие погибшим рабочим.
кроме того, кажется, что вызов socket.destroy()
из рабочих процессов на узле.js v4.9.5
также приводит к розеткам застрял в CLOSE_WAIT
государство. Обновление до узла.js v6.9.5
LTS исправил это для меня.