Подтвердить что ты не робот

Высокая задержка с NodeJS

Эта проблема относится конкретно к Nodejitsu, но подобные эффекты, похоже, происходят и на других VPS. У меня есть игра в режиме реального времени с использованием socket.io, и одна вещь, которую я заметил, - это то, что иногда сервер будет ждать чрезмерного количества времени, прежде чем отвечать. Если в течение этого таймфрейма отправляется несколько запросов, они ведут себя так, как будто все они были поставлены в очередь и обработаны сразу. Я подозреваю, что он смутно коррелирует с присутствием других пользователей на общем оборудовании (как в случае с любым VPS).

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

express = require('express')
http = require('http')

app = express()
server = http.Server(app)

io = require('socket.io').listen(server)

io.sockets.on('connection', function(sock){
    sock.on('perf', function(data, cb){
        cb([Date.now()]); //respond with the current time
    })
})

app.get('/', function(req, res){
    res.header("Access-Control-Allow-Origin", "*")
    res.header("Access-Control-Allow-Methods", "HEAD,GET,PUT,POST,DELETE")
    res.header("Access-Control-Allow-Headers", "X-Requested-With")

    res.end(JSON.stringify([Date.now().toString()])); //http equivalent of perf function
})

server.listen(process.env.PORT || 6655, function(){
    console.log('listening now')
})

У меня была простая пустая HTML-страница с socket.io, которая периодически отправляла событие perf и время, необходимое для срабатывания обратного вызова. И это все равно показывает одно и то же:

graph showing lag spike

Обратите внимание, что длина бара представляет собой квадратный корень времени, а не линейную величину.

Вместо того, чтобы полагаться на socket.io, я использую XHR для выполнения аналогичного измерения текущего времени отклика, результат довольно схож, много ответов с низкой задержкой (хотя и с более высокой базой, чем с websockets, как и ожидалось) и некоторые случайные всплески, которые, похоже, накапливаются.

Странно, что если вы откроете его в нескольких окнах браузера и разных браузерах, похоже, существует корреляция между разными браузерами (и тот факт, что он полностью отсутствует или значительно реже на некоторых серверах), что, кажется, подразумевают, что это явление на стороне сервера. Тем не менее, для некоторых браузеров есть латентные всплески, но не другие, и два окна Chrome одного и того же сеанса кажутся практически точными дубликатами, что говорит о том, что это происходит локально (на каждом компьютере или в браузере, сети мудрый).

Слева направо: Chrome Incognito, Chrome (обычный), Firefox, Chrome (обычный)

charts on four windows

В любом случае, это несколько сбивало меня с толку, и я очень хотел бы понять, что вызывает его и как его исправить.

4b9b3361

Ответ 1

Я предполагаю, что вы проверили, есть ли у вас проблема с CPU или ram.

Единственное, что может замедлить node "удивительным" способом - сборщик мусора - попробуйте запустить node с помощью --trace*, чтобы узнать, что происходит. (См. node --v8-options.)

Я лично считаю, что вы ничего не узнаете от этого, потому что - и это только мое чувство - проблема в другом месте.

С этой идеальной задержкой в ​​500 мс я предполагаю, что у вас есть потеря пакетов. Вы можете проверить с помощью ifconfig, если это общая проблема, а затем tcpdump пакеты и посмотреть, не ретранслируются ли они.

Ответ 2

Я знаю, это может показаться странным, но вы считаете, что это не проблема с node, а с настройкой ОС. Вы проверили свои файловые дескрипторы и количество соединений, которые ОС показывает в сокете? Вы также убедились, что тайм-аут сокета в ОС достаточно низок? Я столкнулся с аналогичными проблемами производительности звучания с другим кодом, и оказалось, что это ОС, а не код. Также проверьте пакет и посмотрите, что он имеет для открытых разрешенных соединений в сокете. Я не рассматривал код node, но столкнулся с аналогичной проблемой с клиентской библиотекой http в java. Приложение просто подперлось, и это была просто проблема с конфигурацией с количеством подключений.

Ответ 3

Причина, по которой вы видите это, - это алгоритм Нагле. Это алгоритм, используемый для ввода/вывода, который некоторое время буферизует данные, а затем отправляет большие куски данных. Он используется для сохранения ваших передач (в сокетах). Подробнее об этом можно прочитать здесь http://en.wikipedia.org/wiki/Nagle's_algorithm

Чтобы отключить алгоритм Нагле (хорошо, если вы хотите как можно быстрее отправить множество небольших запросов), вы можете сделать socket.setNoDelay(true); если вы используете net.Socket(). В случае socket.io я считаю, что Nagle уже отключен по умолчанию для Websockets, но не обязательно для других протоколов. Я бы рекомендовал запустить тест с net.Sockets из node.js, отключить Nagle и посмотреть, что вы получаете.