Гнездо 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 проблема в моей тестовой среде. Но это никогда не проявится. ситуация с подключением.

  1. после подключения сервера сокетов и отключения сети
  2. подключить сервер сокетов в течение длительного времени

Я нашел, что кто-то задал связанный вопрос раньше (многие устаревшие соединения в состоянии 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
  1. Benchmarkt гнездо.Ио

вышеуказанное решение может решить 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 исправил это для меня.