netch80: (Default)
[personal profile] netch80
Никакие способности софта держанию нагрузки не работают, если поток поступает быстрее, чем приёмный процесс вообще способен его принять. Если регулировки потока нет и должны всё принимать, система будет неустойчива и будет выходить в турбулентный режим при переполнении некоторого уровня нагрузки. И неважно, Erlang это или что-то другое: или есть механизм ограничения приёма, потока, или система идёт вразнос.

Жизнерадостное игнорирование этого фактора - основная причина неадекватного поведения наших ранних версий.

А один общий mailbox процесса на все случаи приводит к тому, что управление потоком надо или делать через порты (в частности, выводя толстые потоки в TCP/SCTP/etc., даже если взаимодействуют ноды в кластере), или уметь явно говорить отправителю остановиться. Если бы было несколько очередей, с возможностью настройки каждой из них - можно было бы делать умнее; но сейчас - любое решение получается некорректным.

А существующие костыли закономерно повторяют старые добрые методы работы с очередями, реализованные в маршрутизаторах, начиная с Cisco. Только вот и они не помогают, когда процесс задумался непонятно о чём, а во входной очереди у него 730 тысяч сообщений. Здесь не кран надо менять, а всю систему.

Хочу много очередей с политиками. Размер очереди, простой дроп при заполнении, RED, GRED и так далее. Интересно, NIF'ами это можно сделать? Так, чтобы работало между нодами?

Date: 2012-05-01 06:51 am (UTC)
From: [identity profile] lionet.livejournal.com
У нас есть такие методы:

1. некоторые процессы перед обработкой сообщения смотрят на process_info(self(), messages), и если там их много — игнорируют или временно выходят в режим "ответить всем отлупом"

2. другие процессы перед gen_server:call() делают process_info(whereis(target), messages), и если там плохо — возвращают проблему.

3. есть процессы, которые все входящие сообщения суют в собственную очередь (queue: или ets:), но если она уже достаточно сильно заполнена — отвечают отказом клиенту. Пример: https://github.com/echoteam/mcd

4. если мы сидим и сосём у кролика, то каждое сообщение маркируется таймстемпом. если пришедший таймстемп выходит за рамки разумного (секунды) — сообщение дропается; иначе работаем с ним.

5. есть надсистемный распределённый фреймворк FBI (federated backplane infrastructure), который при превышении метрик и их комбинаций взводит флаги, а весь процессинг идёт в соответствии с флагами (если флаг выставлен — даём отлуп).

RED в принципе где-то бы помог, но скорее на edge (когда трафик входит в кластер: Yaws, например); а там #5 даёт неплохую аппроксимацию его.
Edited Date: 2012-05-01 06:52 am (UTC)

Date: 2012-05-01 09:42 am (UTC)
From: [identity profile] dottedmag.livejournal.com
А в #5 флаги где лежат?

Date: 2012-05-01 10:03 am (UTC)
From: [identity profile] lionet.livejournal.com
Готовые флаги на нодах лежат в ETS и проверяются чем ближе к edge, тем лучше (где-то на входе у внешнего API — сразу за тем местом, где мы начинаем знать, как именно можно грамотно ответить "fail" в рамках того или иного API-вызова).

Центральная нода раздаёт дельты состояния флагов через TCP, а метрики для принятия решений получает от нод через UDP. Примерный синтаксис описания того, как из метрик получить флаги:
flag fast_recreate_views/view/$a/$b "Too many recreates for a view"
    using view/$a/$b/Recreate as Recreate,
          view/$a/$b/GetSearch as GetSearch,
          view/$a/$b/GetCounter as GetCounter
    raise when
        rate(Recreate, Hits, 60) > 10
        and rate(GetSearch, Hits, 60) < 5
        and rate(GetCounter, Hits, 60) < 5
    lower when
        rate(Recreate, Hits, 60) < 2

Date: 2012-05-02 04:53 am (UTC)
From: [identity profile] netch80.livejournal.com
> 1. некоторые процессы перед обработкой сообщения смотрят на process_info(self(), messages), и если там их много — игнорируют или временно выходят в режим "ответить всем отлупом"

Это применяем (сбрасывая всю очередь), но
1) это всё же очень аварийный метод
2) для этого надо посмотреть на свою очередь хотя бы каждые K обработанных сообщений, но если процесс заклинился на чём-то - то эта регулировка не сработает. Такое получается, например, при регулярном gen_call ко вспомогательным сущностям.

> 2. другие процессы перед gen_server:call() делают process_info(whereis(target), messages), и если там плохо — возвращают проблему.

В нашем случае не сработает - отправитель на другой ноде.

> 3. есть процессы, которые все входящие сообщения суют в собственную очередь (queue: или ets:), но если она уже достаточно сильно заполнена — отвечают отказом клиенту. Пример: https://github.com/echoteam/mcd

И такое есть, но опыт той же циски показывает, что в случае, если это не запросы, а просто поток данных, то отказ в приёме новых - худшая стратегия. Лучше сбросить уже принятые и начать принимать заново.

> 4. если мы сидим и сосём у кролика, то каждое сообщение маркируется таймстемпом. если пришедший таймстемп выходит за рамки разумного (секунды) — сообщение дропается; иначе работаем с ним.

См. выше - не помогает - "кролик" на другой ноде способен убить ноду обработчика переполнением её очереди. Убить жёстко - она падает по невозможности выделения памяти.
Если бы не это, то да, метод таймстампа работал бы

> 5. есть надсистемный распределённый фреймворк FBI (federated backplane infrastructure), который при превышении метрик и их комбинаций взводит флаги, а весь процессинг идёт в соответствии с флагами (если флаг выставлен — даём отлуп).

Хм, надо глянуть...

> RED в принципе где-то бы помог, но скорее на edge (когда трафик входит в кластер: Yaws, например); а там #5 даёт неплохую аппроксимацию его.

На входе мы и так проблем не имеет - ну дропнется, и ладно - а вот уже внутри надо что-то делать поумнее.

Date: 2012-05-02 05:14 am (UTC)
From: [identity profile] lionet.livejournal.com
1. process_info(_, messages) можно каждый раз звать, а не раз в N. jfyi.

4. Кролику prefetch выставляйте в 10—100, тогда не убьёт.

6. На входе надо ещё суметь дропнуть — наш опыт показывает, что как раз принять — легче всего; а в середине где-то начинаются узкие места. Поэтому FBI помогает, транслируя эффекты от узких мест в decision-making для edge.
Edited Date: 2012-05-02 05:15 am (UTC)

Date: 2012-05-09 07:01 am (UTC)
From: [identity profile] netch80.livejournal.com
А где про этот FBI почитать? Или это что-то закрытое?
Сейчас поиск по нему ведёт обратно на текущий постинг:)

Date: 2012-05-09 07:06 am (UTC)
From: [identity profile] lionet.livejournal.com
Вот скоро подготовим докладик для ULCAMP::Dev, тогда и внешне-доступный материал появится.

Date: 2012-05-01 10:27 am (UTC)
From: [identity profile] dadv.livejournal.com
В mpd - в том, который работает PPPoE/L2TP/etc. сервером - есть просто механизм управления входящей нагрузкой, отшибающий входящие коннекты с выдачей в лог "Daemon overloaded, ignoring request". Для этого у него как раз очередь с GRED, в которую помещаются как входящие, так и внутренние сообщения между подсистемами и пока заполненность этой очереди ниже определенного порога, принимаются все внешние сообщения (10). При заполненности очереди выше второй константы, все внешние сообщения отбиваются (60), между ними вероятность отбить линейно растёт. Длина самой очереди 8129.

Данные константы плохо работают, когда высокий темп входящих сообщений - норма. Но константы можно и потюнить. Соответствующий код с константами "зашит" в src/ppp.h (макросы SETOVERLOAD(q) и OVERLOAD()).

Profile

netch80: (Default)
netch80

January 2026

S M T W T F S
    1 23
45678910
11121314151617
18192021222324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 3rd, 2026 05:52 am
Powered by Dreamwidth Studios