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

Node.js приложение имеет периодическую медлительность и/или таймауты (не принимает входящие запросы)

Эта проблема убивает стабильность моих производственных серверов.

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

Проблема связана с серьезностью. Иногда то, что должно быть < 100ms запросов, занимает ~ 10 секунд для завершения; иногда они даже не принимаются вообще сервером node. Короче говоря, как будто какая-то случайная задача работает и блокирует поток node в течение определенного периода времени, тем самым замедляя (или даже блокируя) входящие запросы; единственное, что я могу с уверенностью сказать, это то, что необходимость в исправлении-симптоме - это "Тайм-аут шлюза" .

Проблема приходит и идет без предупреждения. Я не смог сопоставить его с использованием ЦП, использованием ОЗУ, временем безотказной работы или любой другой соответствующей статистикой. Я видел, что серверы обрабатывают большие нагрузки, а затем имеют эту ошибку с небольшой нагрузкой, поэтому она даже не связана с нагрузкой. Это не редкость, чтобы увидеть ошибку около 1 утра PST, что является наименьшим временем загрузки в день! Перезапуск приложения node, похоже, может заставить проблему уйти на некоторое время, но это на самом деле не говорит мне многого. Я действительно задаюсь вопросом, может ли ошибка в node.js... не очень утешительная, учитывая, что она убивает мои серверы производства.

Я регистрировал свой сервер с nodetime и вот его jist:

  • CentOS 5.2 работает на облаке Amazon (пример m1.large)
  • Свободная память более 5000 МБ.
  • Размер кучи менее 150 МБ всегда
  • Использование ЦП менее 60% в любое время

Я также проверил мои серверы MongoDB, у которых есть 5% использования ЦП и нет запросов на выполнение > 100 мс, поэтому я очень сомневаюсь, что это узкое место.

Я завернул (почти) весь свой код, используя Q- promises (см. образец кода) и, конечно, избегал вызовов Sync(), таких как чума. Я попытался реплицировать проблему на моем тестовом сервере (OSX), но мало повезло. Конечно, это может быть только из-за того, что производственные серверы используются многими людьми во множестве непредсказуемых способов, которые я просто не могу воспроизвести с помощью стресс-тестов...

4b9b3361

Ответ 1

Через несколько месяцев после того, как я впервые задал этот вопрос, я нашел ответ.

Вкратце, проблема заключалась в том, что я не связывал большой актив при передаче его с одного сервера на другой. Другими словами, я загружал изображение с одного сервера, прежде чем загружать его в ведро S3. Вместо того, чтобы передавать загрузку в загрузку, я загрузил файл в память и затем загрузил его.

Я не уверен, почему это не появилось как всплеск памяти или в других местах моей статистики.

Ответ 2

Мое предположение - Мангуста. Если вы сохраняете большую полезную нагрузку в Mongo, Mongoose может быть довольно медленным из-за того, как он создает объекты Mongoose. Подробнее о проблеме см. https://github.com/LearnBoost/mongoose/issues/950. Если это проблема, вы не увидите ее в самом Mongo, так как запрос возвращается быстро, но для создания экземпляра объекта может потребоваться 75x времени запроса.

Попробуйте настроить таймеры вокруг (process.hrtime()) до и после создания объектов Mongoose, чтобы увидеть, может ли это быть проблемой. Если это проблема, я переключусь на использование драйвера node Mongo напрямую, а не на переход через Mongoose.

Ответ 3

Вы сильно просачиваетесь в память, попробуйте установить для каждого объекта значение null, как только оно вам больше не понадобится! Прочтите это.

Более подробную информацию об устранении утечек памяти можно найти здесь.

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

Попробуйте вызвать сборщик мусора вручную каждую минуту или около того (я не знаю, можете ли вы сделать это в node.js, потому что я больше С++ и php-кодер). Из моего многолетнего опыта работы с С++ я могу сказать, что наиболее вероятная причина замедления вашего приложения с течением времени - утечки памяти, найти их и подключить, вы будете в порядке!

Также предполагается, что вы не кешируете и/или не обрабатываете изображения, аудио или видео в памяти или что-то вроде этой кучи 150M - это много! Это могут быть сотни тысяч или даже миллионы мелких объектов.

У вас не должно быть нехватки памяти для приложения, чтобы замедлить работу... просто поиск свободной памяти с тем, что многие объекты, уже выделенные, являются огромным заданием для распределителя памяти, требуется много времени для выделять каждый новый объект, и когда вы просачиваете все больше и больше памяти, время увеличивается только.

Ответ 4

Является ли "--nouse-idle-connection" ошибкой? вы действительно имеете в виду "--nouse_idle_notification".

Я думаю, что это может быть некоторые проблемы с gc с слишком большим количеством мелких объектов. node представляет собой единый процесс, поэтому смотреть самое загруженное ядро ​​процессора очень важно, чем нагрузка. когда ваша программа работает медленно, вы можете выполнить "gdb node pid" и "bt", чтобы увидеть, что делает занятие node.

Ответ 5

Что бы я сделал, это создать параллельный экземпляр node на том же сервере с каким-то эхо-сервисом и протестировать его. Если он работает нормально, вы сузите свою проблему к своему программному коду (а не к проблеме планировщика/уровня ОС). Затем, шаг за шагом, включите модули и снова проверьте. Конечно, это много работы, занимает много времени, и я не знаю, возможно ли это в вашей системе.

Ответ 6

Если вам нужно сейчас это сделать, вы можете перейти на маршрут резервирования NASA:

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

Очевидно, что это прямолинейно для запросов на чтение, но более сложное для команд, которые записываются в db.

Ответ 7

У нас есть аналогичная проблема с нашим сервером Node.js. В течение нескольких недель он не очень хорошо масштабировался, и мы старались почти все, как вы. Наша проблема заключалась в неявном значении backlog, которое установлено в очень низко для высококонкурентных сред.

http://nodejs.org/api/http.html#http_server_listen_port_hostname_backlog_callback

Настройка отставания на значительно более высокое значение (например, 10000), а также настройка сети в нашем ядре (/etc/sysctl.conf на Linux), как описано в разделе руководства, помогли много. С этого времени мы не имеем никаких тайм-аутов на нашем сервере Node.js.