max-memory-usage-percent

Global

Не принимать почту выше порога памяти
в конфигурации это строкаmax-memory-usage-percent 100внутри блока Global
Аварийный клапан: отказать вежливо вместо того, чтобы упасть

MTA следит, сколько физической памяти занял его собственный процесс. Как только доля переваливает за заданную, приём новой почты прекращается — прямо на стадии MAIL FROM, ответом 452 4.3.2 Server resources temporarily exhausted. Когда память освобождается, приём возобновляется сам: ни перезапуска, ни команды для этого не нужно.

Отказ временный, и в этом весь смысл. 452 — не отказ письму, а просьба повторить: подающая система обязана попробовать ещё раз, а не выбросить письмо. Клапан поэтому ничего не теряет — он только придерживает вход.

Перекрывается вход, а не выход. Всё, что уже стоит в очереди, продолжает уходить: доставку директива не трогает. Так и задумано — очередь разгружается, память освобождается, приём открывается обратно. Отсюда же способ узнать этот 452 в лицо: он приходит вашей платформе рассылки в момент подачи, а не от ящика получателя, и искать его надо в журнале подачи, а не среди отказов доставки.

Что происходит без клапана. Узел с растущей очередью упирается в память операционной системы, и дальше решает уже она: на Linux ядро убивает самый прожорливый процесс, а это и есть сам MTA, pmtad. Сторож pmtawatch поднимет его обратно, но принятое и не записанное потеряно, а после старта узел ещё и перечитывает спул целиком, загружая очередь в память заново, — минуты, в течение которых он не отправляет.

Главная ловушка. Умолчание сменилось между изданиями. В руководстве PowerMTA 5.0 умолчанием было 90 — клапан работал у всех, кто про него даже не знал. В 6.0 умолчание 100, а сотня, как прямо сказано в руководстве, проверку памяти отключает. То есть обновление с пятой версии на шестую молча снимает с узла защиту, если строки в конфигурации нет. Сам конфиг при этом не менялся и выглядит ровно тем же.
Что делает Хаб. Не пишет — узел, поднятый Хабом, живёт с умолчанием 100, то есть без клапана. Данные для расчёта у Хаба есть: при подключении сервера он снимает объём памяти и хранит его у узла, а предполётная проверка отказывает узлу меньше гигабайта и предупреждает на двух. Не хватает только строки в шаблоне конфигурации — и добавлять её надо именно там, а не на узле: канонический конфиг Хаб переписывает целиком, и ручная строка не переживёт следующего применения.
Рекомендуемые значения

Считайте не процент, а остаток. Порог — это запас, который вы оставляете всему остальному: ядру, журналам, дисковому кэшу, а на общем сервере ещё и соседям. Один и тот же процент на разных узлах оставляет разный запас, поэтому чем меньше памяти, тем ниже должен быть порог.

Ориентир — оставить системе от полугигабайта до полутора: при 2 ГБ это 70, при 4 ГБ — 80, при 8 ГБ — 85, при 16 ГБ и больше — 90, то самое умолчание пятой версии.

Ниже 60 не опускайтесь. Порог, который срабатывает на нормальной нагрузке, превращает аварийный отказ в постоянный: платформа получает 452 весь день и рано или поздно считает узел мёртвым. Клапан должен срабатывать редко — это последняя черта, а не способ управлять темпом. Темпом управляют max-msg-rate и total-max-smtp-out, объёмом очереди — spool-max-recipients, и разбираться надо сначала с ними.

Сотня осмысленна только там, где память ограничена снаружи — лимитом контейнера или cgroup, — и вы сознательно отдаёте решение туда. В остальных случаях это не «без ограничений», а «без страховки».

Проценты и запас в гигабайтах — наша рекомендация. Из руководства здесь диапазон 1–100, ответ 452 4.3.2 и умолчания: 100 в издании 6.0, 90 в издании 5.0.
Пример в конфигурации
# директивы уровня узла пишутся в корне файла, без обрамляющего блока
total-max-smtp-in 1000
total-max-smtp-out 5000

# аварийный клапан: на узле с 4 ГБ системе остаётся около 800 МБ
max-memory-usage-percent 80
Соседи выбраны не случайно: это тоже границы на весь экземпляр. Клапан по памяти стоит последним в этом ряду — он срабатывает, когда остальные уже не удержали.
жёлтым — — имена директив, голубым — блоки. Так же они подсвечены и в тексте карточки.
▲

Типичные ошибки и проблемы

что делают не так и чем это кончается3 ошибки▶

Обновились с пятой версии и не заметили, что клапана больше нет

§ 3.3.1.50

Чем чреватоВ 5.0 умолчание было 90, в 6.0 — 100, то есть проверка выключена. Конфигурация не менялась, поведение изменилось: узел, который годами отказывал на пороге сам, теперь принимает почту до упора в память операционной системы.
Как заметитьПосле обновления узел стал уходить в перезапуск под нагрузкой, хотя до обновления на той же нагрузке только притормаживал приём.
Как правильноЗадать порог явно — не полагаться на умолчание ни в одну, ни в другую сторону. Строка в конфигурации есть — значит клапан есть и вы знаете, на каком он значении.

Ставят порог низко, чтобы «наверняка»

наш опыт

Чем чреватоЗначение вроде 50 срабатывает на обычной рабочей нагрузке, и временный отказ перестаёт быть аварийным: платформа получает 452 постоянно. Формально всё верно — письма не теряются, — но подача идёт рывками, а очередь на стороне платформы растёт.
Как заметить452 в журнале подачи идут ровным потоком, а не всплесками; при этом память узла далека от исчерпания.
Как правильноПоднять порог так, чтобы он оставлял системе от полугигабайта до полутора, и разбираться с темпом через лимиты очередей, а не через клапан.

Ищут причину 452 на стороне получателя

наш опыт

Чем чреватоОтказ выглядит как обычный временный отказ SMTP, и его начинают объяснять репутацией, лимитами провайдера или блокировкой адреса. Настоящая причина — свой же узел на стадии приёма, и время уходит не туда.
Как заметить452 приходит на MAIL FROM, до RCPT дело не доходит, и текст ответа говорит про ресурсы сервера, а не про получателя или отправителя.
Как правильноЧитать ответ целиком. 452 4.3.2 Server resources temporarily exhausted — это ответ вашего узла подающей системе; смотреть надо память узла, а не доставляемость.
Совместимость
PowerMTA 6.0
описана в руководстве этой версии · платформа: любая
С какой версии директива доступна, вендор указывает не для всех — здесь пометки нет. Имя встречается и в издании руководства 5.0.
Справочные данные
Синтаксис
max-memory-usage-percent N
Значения
целое от 1 до 100; 100 отключает проверку
Умолчание
100 § 3.3.1.50
Применение
reload, перезапуск не нужен
Очередь
уже поставленное в очередь не затронет
Где писать
Global
Сколько раз
один раз в блоке
Всё здесь — из руководства, с разделом.
Наследование
Наследования нет: директива пишется один раз в корне файла и действует на весь экземпляр. В блоке адреса отправки или получателя её не задать — память у узла одна, и порог к ней тоже один. Подхватывается по pmta reload, перезапуск сервиса не нужен.
Как проверить на узле
Отдельной команды нет: pmta show settings показывает настройки очереди и адреса отправки, а директив уровня узла в её выводе не бывает. Поэтому смотрим сам конфиг — вместе с подключаемыми файлами — и расход памяти процесса:
grep -rn max-memory-usage-percent /etc/pmta/
ps -o pid,rss,%mem,comm -C pmtad
Пустой ответ первой команды означает, что клапана нет: узел работает с умолчанием 100. Во второй колонка %MEM — та самая доля, с которой сравнивается порог; рядом с pmtad обычно виден pmtawatch, сторож, он памяти почти не ест. Хаб текущий расход памяти узла пока не собирает: в мониторинге показан объём памяти машины, снятый при подключении, а не занятость.
В Хабе
Цена ошибки
обратимо: вредит, пока стоит
Сценарии
Планирование мощности · Разобрать зависшую очередь