Как стать автором
Обновить

Комментарии 26

Секунду, 503 — это разве не падает?
Так не честно.
НЛО прилетело и опубликовало эту надпись здесь
блин, я почти поверил, что на хабре стало можно удалять комментарии :))

UPD. понятно почему: вы удачно мимикрировали под надпись (комментарий был изменен)
Удачно было бы, если бы была буква «ё». В интерфейсе Хабра она есть.
НЛО прилетело и опубликовало эту надпись здесь
Я не совсем понял, как все-таки работает toobusy(). Все ясно с callstack — замеряется раз в 500 мс. На основе этих данных можно при всех вызовах toobusy возвращать true. Но тогда получается, что в этом случае очередь может за 500мс рассосаться и при этом продолжить всем отвечать ошибкой. Далее предположим нагрузка есть, сделан новый замер длины очереди. Очередь пустая (но нагрузка до сих пор большая, просто всем отвечаем 503). Функция toobusy начинает всем отвечать false. И отвечает так в течение 500мс. В течение этого времени запросы начинают обрабатываться и все равно сервер ложится…

Я к тому, что по идее надо делать какое-то распределение ответов между замерами. Например, под нагрузкой отвечать toobusy() = false каждому десятому. Но как это сделать?
НЛО прилетело и опубликовало эту надпись здесь
Я тут просто мимо проходил, но вроде, судя по коду, там так и делается:

Handle<Value> TooBusy(const Arguments& args) {
    // No HandleScope required, because this function allocates no
    // v8 classes that reside on the heap.
    bool block = false;
    if (s_currentLag > HIGH_WATER_MARK_MS) {
        // probabilistically block requests proportional to how
        // far behind we are.
        double pctToBlock = ((s_currentLag - HIGH_WATER_MARK_MS) /
                             (double) HIGH_WATER_MARK_MS) * 100.0;
        double r = (rand() / (double) RAND_MAX) * 100.0;
        if (r < pctToBlock) block = true;
    }
    return block ? True() : False();
}
/humour mode on/ Требуем опубликования второй части статьи: «Пишем сервер, который не взламывается под атаками».
Краткое содержание: отключаем от сети, делаем только оффлайн доступ… профит. /humour mode off/

Но на самом деле, серьезно. Это вообще не та задача которую node.js должен решать, в принципе.
Конечно это не «антиддос на пхп», но все же, несмотря на то что node.js сам себе сервер — задачу отброса клиента по превышению нагрузки должен решать специальный лоад-балансер, отдельная софтина.
Вы наверное никогда не были в ситуации, когда нагрузка резко возрастает. Понятно, что можно подготовиться, поставить железо, балансеры, расширить каналы и т.д. Но это подготовка. Иногда бывает так, что есть приложение и на него именно сейчас идет в 10 раз больше пользователей, чем обычно. В этом случае могут «помочь» подобные решения — это легко прикрутить уже под нагрузкой. Понятно, что большинство пользователей все равно увидит ошибку, но не все. Обслуживать 20% запросов гораздо лучше, чем обслуживать 0%.
Речь о том, что когда нагрузка на node.js, php, mysql, apache, что-то еще резко возрастает следует воспользоваться сторонней тулзой для решения вопроса с нагрузкой.
Кроме того, что это будет инструмент специально заточенный под лоад-балансинг со всеми его плюсами, имея сторонний инструмент — Вы не будете смешивать «нагрузку от фильтрации нагрузки» и «нагрузку от обработки клиентских запросов» — что тоже достаточно важно.
А займет это не больше времени, чем поставить либу для node.js. Благо балансирующего софта навалом.
Обслуживать 20% запросов гораздо лучше, чем обслуживать 0%.
А обслуживать 40% запросов и четко понимать на что уходят ресурсы и иметь данные в привычном для сисадминов виде еще лучше, разве нет?
Есть ссылки на эти самые инструменты, которые позволяют «фильтровать» часть запросов в зависимости от нагрузки? Как эти инструменты вообще понимают насколько нагружен бэкэнд? Было бы интересно почитать.
ну то есть обычное правило — наперед выставляем nginx, сзади нода — и получаем сразу не только это, но и еще 100500 плюшек :)
Нет, это — именно та самая задача, которую должна решать нода. В противном случае даже самый хороший балансировщик нагрузки не спасет от «эффекта домино».

Кроме того, ответы 503 — это самый красивый способ получения обратной связи балансировщиком.
Я правильно понимаю, что когда node-toobusy обнаружит что до начала обработки запроса более 70 мс, то пользователь получит 503?
Нет. Никакие 70мс нигде не указаны — в коде вообще нет никаких констант времени, кроме 1сек (интервал проверки).
Во-первых, в посте упоминается «значение чувствительности» со ссылкой на maxLag, maximum amount of time in milliseconds that the event queue is behind.

Во-вторых, в исходном коде есть временной параметр:

static unsigned int HIGH_WATER_MARK_MS = 70;


Вы тот код смотрели?
А, точно, почему-то именно эти константы я и проглядел…

Но это — порог лага для тестового таймера, а не для запроса. То есть время начала запроса и 503 никак напрямую не связаны. Кроме того, чем меньше превышение лага над 70мс, тем меньше вероятность отказа отвечать на конкретный запрос.
Во-первых, я и написал время до «начала обработки запроса», то есть задержка, лаг.
Во-вторых, таймауты традиционно меряют секундами, десятками секунд.

Меня удивляет, что кто-то решил отшвыривать клиента в случае некой задержки в 70 мс.
Это — не тайм-аут в обычном смысле этого слова. Тайм-аут — это ограничение времени на полное формирование страницы. А здесь измеряется время, необходимое для полного оборота очереди событий (и ограничение на этот оборот — 500+70=570мс, кстати говоря). В процессе формирования страницы очередь событий может «провернуться» несколько раз (как минимум — по разу на каждый запрос к БД, если не распараллеливать их).
Злые вы…
По моему, хороший способ подстраховки от внезапного наплыва пользователей, особенно в стадии развития проекта, когда нет времени и сил на настройку и мониторинг сторонних тулов.
По мне, так было бы лучше сразу не пятисотить. Лучше что-нибудь такое, что честно мониторит бекенды, а если они заняты — просто переселяет пользователя в медленный пул, честно его предупредив перед этим. А тем временем поднять еще бекендов в автоматическом или полуавтоматическом режимах. Например, с помощью модулей openresty легко можно так сделать на lua. Сразу же активировать несколько ступеней защиты.
В общем как-то это все неправильно — кидать пачку пятисотых, если мы сильно заняты, и больше ничего не делать.
А всякие nginx'ы, lighthttpd'ы и аналоги не спасут? Мне казалось, они как раз для решения таких проблем.
Из коробки не очень получается.
Проблема в том, что для балансировки нам нужно точно знать состояние бекендов. Мы сейчас у себя исследуем такую штуку. Правда там похапэ, это несколько сложнее, чем нода )) Авторизация у нас по ключам.

1. Сделано. Используем openresty. В LUA вынесли все коды ошибок и сделали firewall. Запрос прежде всего должен пробиться через lua, где ему скажут, можно ли вообще идти дальше. Если можно, то с какими лимитами и на какой бекенд.
2. Еще не сделано. По приложениям ползает паук, который проводит самодиагностику и оценку производительности бекенда со всеми его связями и зависимостями — по факту и в прогнозе на минуту вперед. Теоритически выставляет некое количество баллов для бекенда. Самый быстрый и незанятый получает, скажем 100 баллов. Если есть затупы, баллов будет меньше. Информация складывается опять в LUA, через, скажем redis. Тут все работает напрямую, очень быстро.
3. Еще не сделано. Есть еще несколько гипервизоров, которым можно сказать поднять дополнительные мощности — виртуалки с бекендами.
Если мы везде тупим, то пора поднимать еще виртуалку в большом геокластере.

На выходе получаем nginx-as-web-application, который точно знает, куда и как ему зарутить запрос.
Тема вообще интересная, рекомендую ))
Зарегистрируйтесь на Хабре, чтобы оставить комментарий