Эта проблема убивает стабильность моих производственных серверов.
Напомним, основная идея заключается в том, что мой сервер node иногда прерывисто замедляется, иногда приводя к таймаутам шлюза. Насколько я могу судить по моим журналам, что-то блокирует поток node (что означает, что входящий запрос не принимается), но я не могу на всю жизнь выяснить, что.
Проблема связана с серьезностью. Иногда то, что должно быть < 100ms запросов, занимает ~ 10 секунд для завершения; иногда они даже не принимаются вообще сервером node. Короче говоря, как будто какая-то случайная задача работает и блокирует поток node в течение определенного периода времени, тем самым замедляя (или даже блокируя) входящие запросы; единственное, что я могу с уверенностью сказать, это то, что необходимость в исправлении-симптоме - это "Тайм-аут шлюза" .
Проблема приходит и идет без предупреждения. Я не смог сопоставить его с использованием ЦП, использованием ОЗУ, временем безотказной работы или любой другой соответствующей статистикой. Я видел, что серверы обрабатывают большие нагрузки, а затем имеют эту ошибку с небольшой нагрузкой, поэтому она даже не связана с нагрузкой. Это не редкость, чтобы увидеть ошибку около 1 утра PST, что является наименьшим временем загрузки в день! Перезапуск приложения node, похоже, может заставить проблему уйти на некоторое время, но это на самом деле не говорит мне многого. Я действительно задаюсь вопросом, может ли ошибка в node.js... не очень утешительная, учитывая, что она убивает мои серверы производства.
- Первое, что я сделал, это убедиться, что я обновил node.js до последнего (0.8.12), а также всех моих модулей (здесь они). Конечно, у меня также много ловушек ошибок. Я не делаю ничего напуганного, как распечатывать партии на консоль или записывать много файлов.
- Сначала Я думал, что это были исходящие HTTP-запросы, блокирующие входящий сокет, потому что явное промежуточное программное обеспечение даже не собирало входящий запрос, но я отказался от этой теории, потому что она выглядит как и сам поток node стал занят.
- Затем я просмотрел весь свой код с помощью JSHint и зафиксировал буквально каждое предупреждение, в том числе несколько случайных глобальных переменных (забыв написать "var" ), но это не помогло
- После этого я предположил, что, возможно, у меня заканчивается память. Но мои снимки кучи через nodetime выглядят неплохо сейчас (описано ниже).
- Все еще думая, что память может быть проблемой, я взглянул на сборку мусора. Я включил флаг -nouse-idle-notification и сделал еще одну оптимизацию кода для NULL-объектов, когда они не были нужны.
- Все еще убедившись, что проблема памяти, я добавил флаг -expose-gc и выполнил gc(); команда каждую минуту. Это ничего не изменило, за исключением того, что иногда делалось несколько медленнее.
- В отчаянной попытке я настраиваю модуль "кластер", чтобы использовать 2 рабочих и автоматически перезапускать их каждые 30 мин. Тем не менее, не повезло.
- Я увеличил ulimit до более чем 10 000 и следил за открытыми файлами. Кажется, 300 открытых файлов (или сокетов) в приложении node.js, и увеличение ulimit не оказало никакого влияния.
Я регистрировал свой сервер с nodetime и вот его jist:
- CentOS 5.2 работает на облаке Amazon (пример m1.large)
- Свободная память более 5000 МБ.
- Размер кучи менее 150 МБ всегда
- Использование ЦП менее 60% в любое время
Я также проверил мои серверы MongoDB, у которых есть 5% использования ЦП и нет запросов на выполнение > 100 мс, поэтому я очень сомневаюсь, что это узкое место.
Я завернул (почти) весь свой код, используя Q- promises (см. образец кода) и, конечно, избегал вызовов Sync(), таких как чума. Я попытался реплицировать проблему на моем тестовом сервере (OSX), но мало повезло. Конечно, это может быть только из-за того, что производственные серверы используются многими людьми во множестве непредсказуемых способов, которые я просто не могу воспроизвести с помощью стресс-тестов...