WebSocket прекращает получать данные после 15-20 минут потока данных - NodeJS - PullRequest
0 голосов
/ 09 мая 2019

Код

var websock = net.createServer(function(sock) {
  sock.pipe(sock);
  sock.setEncoding('utf8');
  sock.setKeepAlive(true);

  sock.on("data", function(d) {
       console.log("websock", d);
  });

  sock.on('end', function() {
      console.log('websock disconnected');
  });
});

websock.listen(777, '127.0.0.1');

Через несколько минут ~ 15 минут код обратного вызова в sock.on ("data", function () {}), похоже, не работает.почему это так?Я проверил console.log, там нет журнала со строкой "websock отключен".

если сокет не отключен и если нет ошибки, что произошло с соединением сокета или потоком данных?

С другой стороны (сторона сервера, отправитель данных), кажетсянепрерывная потоковая передача данных, пока клиентская часть (приложение nodejs) перестала получать данные.

1 Ответ

2 голосов
/ 10 мая 2019

Проблема возникает из-за того, что вы используете конвейерный механизм для отображения данных, которые никогда не используются на исходной стороне (связь однонаправлена):

sock.pipe(sock);

Это заставляет ваш код работать как эхо-сервер. Ваш сокет "sock" является дуплексным потоком (то есть как читаемым - для входящих данных, которые вы получаете, так и записываемым - для исходящих данных, которые вы отправляете обратно).

Быстрое решение, если вам не нужно отвечать, и вам просто нужно получить данные, - просто удалите "sock.pipe (sock);" линия . Чтобы узнать объяснение, читайте дальше.

Скорее всего, ваш источник данных (упомянутое вами приложение MT5) отправляет данные непрерывно, и он вообще не читает то, что вы отправляете обратно. Итак, ваш код продолжает отображать полученные данные, используя sock.pipe (sock), заполняя исходящий буфер, который никогда не используется. Однако механизм канала потоков Nodejs обрабатывает противодавление , что означает, что когда два потока (читаемый и записываемый) соединены каналом, если исходящий буфер заполняется (достигая верхнего водяного знака), читаемый поток приостановлен, чтобы предотвратить «переполнение» записываемого потока.

Подробнее о противодавлении вы можете прочитать в документах Nodejs . Этот фрагмент, в частности, описывает, как потоки обрабатывают противодавление:

В Node.js источником является поток для чтения, а потребителем - поток для записи [...]

Момент, когда срабатывает противодавление, можно сузить точно до возвращаемого значения функции .write (). [...]

В любом случае, когда буфер данных превысил highWaterMark или очередь записи в данный момент занята, .write () вернет false.

Когда возвращается ложное значение, срабатывает система противодавления. Приостановка поступающего читаемого потока от отправки любых данных и ожидание, пока потребитель не будет снова готов.

Ниже вы можете найти мои настройки, чтобы показать, где возникает обратное давление; Есть два файла, server.js и client.js. Если вы запустите их оба, сервер вскоре напишет в консоль «BACKPRESSURE». Поскольку сервер не обрабатывает обратное давление (он игнорирует, что sock.write начинает возвращать false в некоторый момент), исходящий буфер заполняется и заполняется, занимая больше памяти, в то время как в вашем сценарии socket.pipe обрабатывал обратное давление и, таким образом, он приостанавливал поток входящих сообщений.

Сервер:

// ----------------------------------------
// server.js

var net = require('net');

var server = net.createServer(function (socket) {
    console.log('new connection');

    // socket.pipe(socket); // replaced with socket.write on each 'data' event

    socket.setEncoding('utf8');
    socket.setKeepAlive(true);

    socket.on("data", function (d) {
        console.log("received: ", d);
        var result = socket.write(d);
        console.log(result ? 'write ok' : 'BACKPRESSURE');
    });

    socket.on('error', function (err) {
        console.log('client error:', err);
    });

    socket.on('end', function () {
        console.log('client disconnected');
    });
});

server.listen(10777, '127.0.0.1', () => {
    console.log('server listening...');
});

Клиент:

// ----------------------------------------
// client.js

var net = require('net');

var client = net.createConnection(10777, () => {
    console.log('connected to server!' + new Date().toISOString());

    var count = 1;
    var date;
    while(count < 35000) {
        count++;

        date = new Date().toISOString() + '_' + count;
        console.log('sending: ', date);
        client.write(date + '\n');
    }
});

client.on('data', (data) => {
    console.log('received:', data.toString());
});
client.on('end', () => {
    console.log('disconnected from server');
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...