Высокая задержка с 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
событие и время, сколько времени потребовалось на обратный вызов, чтобы выстрелить. И это все еще показывает то же самое:
Обратите внимание, что длина столбца представляет квадратный корень количества времени, а не линейной величины.
Когда вместо того, чтобы полагаться на socket.io, я использую XHR для аналогичного измерения текущего времени отклика, результат довольно схожий, много откликов с низкой задержкой (хотя с более высокой базовой линией, чем у веб-сокетов, как и ожидалось) и некоторые случайные шипы, которые, кажется, накапливаются.
Странно то, что если вы открываете его в нескольких окнах браузера и в разных браузерах, кажется, что существует корреляция между различными браузерами (и тот факт, что он полностью отсутствует или значительно реже на некоторых серверах), что, по-видимому, означает, что явление на стороне сервера. Однако в некоторых браузерах наблюдаются всплески задержки, но не в других, и два окна Chrome, относящиеся к одному и тому же сеансу, представляются практически точными дубликатами, что говорит о том, что это происходит локально (на компьютере или на браузере, в сети). мудрый).
Слева направо: Chrome Incognito, Chrome (обычный), Firefox, Chrome (обычный)
Во всяком случае, это сбивало меня с толку в течение нескольких месяцев, и я действительно хотел бы понять, что вызывает это и как это исправить.
3 ответа
Я полагаю, вы проверили, есть ли у вас проблемы с процессором или оперативной памятью.
Единственное, что может "удивить" замедлить работу узла - сборщик мусора - попробуйте запустить ваш узел с --trace*
чтобы увидеть, что происходит. (Увидеть node --v8-options
.)
Я лично заверяю, что вы ничего от этого не узнаете, потому что - и это только мое чувство - проблема в другом.
С этой идеальной задержкой, кратной 500 мс, я предполагаю, что у вас потеря пакетов. Вы можете проверить с ifconfig
если это общая проблема, а затем tcpdump
пакеты и посмотреть, если они передают.
Причина, почему вы видите это из-за алгоритма Нейгла. Это алгоритм, используемый для ввода-вывода, который некоторое время буферизует данные, а затем отправляет большие порции данных. Он используется для сохранения ваших передач (в розетках). Вы можете прочитать больше об этом здесь http://en.wikipedia.org/wiki/Nagle%27s_algorithm
Чтобы отключить алгоритм Nagle (хорошо, если вы хотите посылать множество маленьких запросов как можно быстрее), вы можете сделать socket.setNoDelay(true); если вы используете net.Socket() . В случае с socket.io я считаю, что Nagle уже отключен по умолчанию для веб-сокетов, но не обязательно для других протоколов. Я бы порекомендовал запустить тест с net.Sockets из node.js, отключить Nagle и посмотреть, что вы получите.
Я знаю, что это может звучать странно, но вы считаете, что это не проблема с узлом, а с настройкой ОС. Вы проверили свои файловые дескрипторы и количество соединений, которые ОС показывает к сокету? Вы также убедились, что время ожидания сокета в ОС достаточно мало? Я столкнулся с похожими проблемами производительности другого кода, и это оказалась ОС, а не код. Также проверьте пакет и посмотрите, что он имеет для открытых разрешенных соединений на сокете. Я не смотрел на код узла, но столкнулся с аналогичной проблемой с клиентской библиотекой http в java. Приложение только что скопировало, и это была просто проблема конфигурации с количеством соединений.