32. Конфигурация повторов

Перевод выполнен Алексеем Паутовым в рамках некоммерческого проекта RussianLDP (http://www.rldp.ru/). Именно на этом сайте и надлежит искать новые версии, если таковые будут.

32. Конфигурация повторов

Секция retry рабочего файла конфигурации содержит список правил повторов, которые контролируют, как часто exim пытается доставить сообщения, которые нельзя было доставить при первой попытке. Если правила повторов вообще отсутствуют, временные ошибки обрабатываются как постоянные. Опция командной строки -brt может использоваться для проверки, какие правила повторов будут использоваться для данного адреса, домена и ошибки.

Самая обычная причина повторов: временная ошибка доставки на удалённый хост, поскольку хост отключен или недоступен из-за проблем с сетью. Обработка повторов exim в этом случае основана на применении к хостам (строго по IP-адресам), не на сообщениях. Таким образом, если одно сообщение было недавно задержано, доставка нового сообщения на тот же самый хост не пробуется немедленно, а ожидается достижения времени повтора хоста. Если установлен выбор протоколов retry_defer, сообщение "retry time not reached" записывается в главный протокол каждый раз, когда доставка пропущена по этой причине. Раздел 44.2 содержит более подробную информацию о обработке ошибок в течение удалённых доставок.

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

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

32.1. Правила повторов

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

Шаблон задает любой отдельный элемент, который может появляться в списке адресов (смотрите раздел 10.18 ). Фактически, он обрабатывается как одноэлементный список адресов, что означает, что он раскрыт до начала сравнения с задержанным адресом. Обработка списка адресов относится к имени домена, как будто ему предшествовало *@, что делает возможным для многих правил повтора начинаться с домена. Например,

lookingglass.fict.example        *  F,24h,30m;
предоставляет правило для любого адреса в домене lookingglass.fict.example, тогда как:
alice@lookingglass.fict.example  *  F,24h,30m;
применяется лишь к временным ошибкам, вовлекшим локальную часть alice. Практически, почти все правила начинаются с шаблона без локальной части.

Предупреждение: Если Вы используете в шаблоне правила роутинга регулярное выражение, оно должно совпадать с полным адресом, а не только с доменом, поскольку именно так регулярные выражения работают в списке адресов:

^\Nxyz\d+\.abc\.example$\N        *  G,1h,10m,2     Неправильно
^\N[^@]+@xyz\d+\.abc\.example$\N  *  G,1h,10m,2     Правильно

32.2. Выбор, какие правила используются для ошибок адреса

Когда exim ищет правило повтора после неудачной попытки роутинга (например, после таймаута DNS), каждая строка в конфигурации повторов сравнивается с полным адресом лишь если для роутера задана опция retry_use_local_part. Иначе используется только домен за исключением случая, когда сравнивается с регулярным выражением, когда локальная часть адреса заменена *. Домен может самостоятельно соответствовать шаблону или образцу, начинающемуся с *@. По умолчанию retry_use_local_part истинна для роутеров, где истинна check_local_user, и ложна для других роутеров.

Точно так же exim ищет правило повтора после неудачной локальной доставки (например, после ошибки переполнения почтового ящика), каждая строка в конфигурации повторов сравнивается с полным адресом лишь если для транспорта установлена retry_use_local_part (это истинно по умолчанию для всех локальных транспортов).

Однако, когда exim ищет правило повтора после ошибки адреса для удалённой доставки (SMTP-ответ 4xx для адреса получателя), в качестве ключа при поиске правила повтора всегда используется весь адрес. Найденное правило используется для создания времени повтора для неудачного адреса.

32.3. Выбор, какое правило используется для хоста и сообщения о ошибке

Для временной ошибки, которая не связана с индивидуальным адресом (например, таймаут соединения), каждая строка в конфигурации повторов проверяется дважды. Вначале, имя удалённого хоста используется как доменное имя (предваряемое *@ при сравнении с регулярным выражением). Если оно не соответствует строке, подобным образом пробуется домен из адреса электронной почты. Например, предположим, что MX-записи для a.b.c.example таковы:

a.b.c.example  MX  5
x.y.z.example  MX  6
p.q.r.example  MX  7
m.n.o.example
и правила повторов таковы:
p.q.r.example    *      F,24h,30m;
a.b.c.example    *      F,4d,45m;
и доставка к хосту x.y.z.example переносит ошибку соединения. Первое правило не соответствует ни хосту, ни домену, таким образом, exim смотрит второе правило. Оно не соответствует хосту, но совпадает с доменом, таким образом, оно используется для вычисления времени повтора для хоста x.y.z.example. Тем временем, exim пробует осуществить доставку на p.q.r.example. Если при этом также происходит ошибка хоста, используется первое правило повтора, поскольку оно совпадает с хостом. Другими словами, временные ошибки доставки к хосту p.q.r.example используют первое правило для определения времён повтора, но для все других хостов домена a.b.c.example используется второе правило. Также второе правило используется, если временная ошибка происходит при роутигге к a.b.c.example. Отметьте: имя хоста используется при сравнении с шаблонами, а не с его IP-адресом. Однако, если сообщение роутится напрямую к IP-адресу без использования имени хоста, например, если роутер manualroute содержит установку типа:
route_list = *.a.example  192.168.34.23

Тогда, используемое при поиске правила повтора имя хоста, текстовая форма IP-адреса.

32.4. Правила повтора для специфических ошибок

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

  • auth_failed: Аутентификация неудачна при попытке отправить на хост в списке hosts_require_auth в транспорте smtp.
  • data_4xx: Ошибка 4xx получается для исходящей команды DATA немедленно после команды или после посылки данных сообщения.
  • mail_4xx: Ошибка 4xx получается для исходящей команды MAIL.
  • rcpt_4xx: Ошибка 4xx получается для исходящей команды RCPT. Для трёх ошибок 4xx первый или оба из x может быть дан как специфическая цифра, например: mail_45x или rcpt_436. Например, для распознания ошибки 452 данной команде RCPT для адресов в определённом домене, имеющих повторы каждые десять минут с одночасовым таймаутом, Вы могли бы установить правило повтора такой формы:
    the.domain.name  rcpt_452   F,1h,10m
    

    Эти ошибки применяются к обоим, исходящему SMTP (транспорт smtp), и исходящему LMTP (транспорт lmtp или smtp в режиме LMTP).

  • lost_connection: Сервер неожиданно закрыт SMTP-соединение. Конечно, для этого могут быть законные причины (хост выключили, сеть оборвалась), но если для одного и того же хоста это часто повторяется, это указывает на нечто странное.
  • refused_MX: Отказано в соединении к хосту, полученному из MX-записи.
  • refused_A: Отказано в соединении к хосту, полученному не из MX-записи.
  • refused: Отказано в соединении.
  • timeout_connect_MX: Таймаут попытки соединения с хостом, полученным из MX-записи.
  • timeout_connect_A: Таймаут попытки соединения с хостом, полученным не из MX-записи.
  • timeout_connect: Таймаут попытки соединения.
  • timeout_MX: Был таймаут при соединениии или во время SMTP-сессии с хостом, полученным из записи MX.
  • timeout_A: Был таймаут при соединениии или во время SMTP-сессии с хостом, полученным не из записи MX.
  • timeout: Был таймаут при соединениии или во время SMTP-сессии.
  • tls_required: Сервер обязан был использовать TLS (он соответствовал hosts_require_tls в транспорте smtp), но не предлагал TLS, или ответил 4xx на STARTTLS, или была проблема с установкой TLS-подключения.
  • quota При локальной доставке транспортом appendfile была превышена квота почтового ящика.
  • quota_<time> При локальной доставке транспортом appendfile была превышена квота почтового ящика, и к почтовому ящику не обращались <time>. Например, quota_4d применяется к ошибкам квоты, когда к ящику не обращались в течение 4-х дней. Идея quota_<time>: сделать возможными более короткие таймауты, когда почтовый ящик полон и не читается владельцем. Идеально, это должно быть основано на последнем времени, когда пользователь обращался к почтовому ящику. Однако, это не всегда можно определить. Exim использует следующие эвристические правила:
    • Если почтовый ящик один файл, используется время последнего доступа (atime). Поскольку новые сообщения не доставляются (так как у почтовго ящика превышена квота), exim не обращается к файлу, следовательно, это последнее время доступа пользователя.
    • Для доставки в maildir используется время последней модификации подкаталога new. Так как превышена квота, в ней не создаётся новых файлов, поскольку новые сообщения не доставляются. Предполагается, что любые изменения new являются результатом перемещения новых сообщений в cur пользовательским MUA при первом чтении. Используемое время, это когда пользователь последний раз читал новые сообщения.
    • Для других видов многофайлового почтового ящика время последнего доступа не может быть получено из времени последнего обращения, таким образом, правило повтора, использующее этот тип поля ошибки, никогда не совпадёт. Ошибки квоты применяются к обоим: системной квоте и собственному механизму квот exim в транспорте appendfile. Ошибка quota также применяется, когда локальная доставка задержана, поскольку заполнился раздел диска (ошибка ENOSPC).

32.5. Правила повторов для специфических отправителей

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

senders=<address list>

Тогда расчёт времени повтора определяет четвёртый элемент. Например:

*   rcpt_4xx   senders=:   F,1h,30m
совпадает получатель 4xx ошибок для рикошетов, посланных к любому адресу любого хоста. Если список адресов содержит пробелы, он должен быть заключён в кавычки. Например:
a.domain rcpt_452 senders="xb.dom : yc.dom" G,8h,10m,1.5

Предупреждение: Это средство может быть бесполезным, если оно используется для ошибок хостов (которые не зависят от получателя). Причина в том, что отправитель используется лишь для совпадения с правилом повтора. Как только для ошибки хоста было найдено правило, его содержимое для установки времени повтора для хоста, и это применяется ко всем сообщениям, а не только к тем, у которых специфический отправитель. Когда правило тестируется с использованием -brt, Вы можете предоставить отправителя, используя опцию командной строки -f, как тут:

exim -f "" -brt user@dom.ain

Если Вы не устанавливаете -f с -brt, правило повтора, содержащее список отправителей, никогда не совпадёт.

32.6. Параметры повтора

Третье (или четвёртое, если присутствует список отправителей) поле в правиле повтора представляет собой последовательность набора параметров повторения, разделённых точкой с запятой. Каждый набор состоит из:

<letter>,<cutoff time>,<arguments>

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

  • F: повторять с фиксированными интервалами. Существует один параметр времени, определяющий интервал.
  • G: повторять в геометрически увеличивающихся интервалах. Первый аргумент определяет начальное значение для интервала, а второй задает множитель, используемый для увеличения интервала при каждом повторении.
  • H: повторять со случайными интервалами. Аргументы такие же, как для G. Для каждого повтора предыдущий интервал умножается на фактор для получения максимума следующего интервала.

Минимальный интервал: первый аргумент параметра, а актуальный интервал выбирается случайным образом из диапазона между ними. Такое поведение, как было найдено, было полезным в кластерных конфигурациях, когда все члены кластера перезапускаются одновременно и поэтому могут синхронизировать свои времена обработки очереди.

Когда вычисляется следующее время повтора, по порядку сканируются определения алгоритма, пока не достигнут тот, чьё время уменьшения ещё не прошло. Тогда он используется для вычисления нового времени повтора, которое более позднее, чем текущее время. В случае фиксированных интервалов повторов это означает просто добавление интервала к текущему времени. Для геометрически увеличивающихся интервалов интервалы повторов вычисляются из параметров правил, до большего, чем предыдущий найденный интервал.

Переменная главной конфигурации retry_interval_max ограничивает максимальный интервал между повторами. Она не может быть установлена более, чем в 24h, что и является её значением по умолчанию.

Один удалённый домен может иметь несколько ассоциированных с ним хостов, и каждый хост может иметь более одного IP-адреса. Алгоритмы повтора отобраны на основе имени домена, но применяются к каждому адресу независимо. Если, например, хост имеет два IP-адреса, и один невозможно использовать, exim будет генерировать время повтора для него, и не пробует его использовать до наступления следующего времени повтора. Таким образом, вероятно, работающий IP-адрес будет пробоваться первым в большинстве случаев.

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

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

Данные в базе данных подсказок повторов могут быть проверены путём использования программ exim_dumpdb или exim_fixdb (смотрите раздел 49). Последняя утилита также может использоваться для изменения данных. Скрипт exinext может использоваться для нахождения следующего времени повтора для хостов, ассоциированных со специфическим почтовым доменом, и для задержанных локальных доставок.

32.7. Примеры правил повтора

Вот некоторые примеры правил повтора:

alice@wonderland.fict.example quota_5d  F,7d,3h
wonderland.fict.example       quota_5d
wonderland.fict.example       *         F,1h,15m; G,2d,1h,2;
lookingglass.fict.example     *         F,24h,30m;
*                 refused_A   F,2h,20m;
*                 *           F,2h,15m; G,16h,1h,1.5; F,5d,8h

Первое правило устанавливает специальную обработку для почты на alice@wonderland.fict.example, когда происходит ошибка превышения квоты, и почтовый ящик не читался по крайней мере 5 дней. Повторы продолжаются каждые три часа в течение 7 дней. Второе правило обрабатывает превышение квоты для всех остальных локальных частей в wonderland.fict.example: отсутствие локальной части имеет тот же эффект, что и подстановка *@. Поскольку не предоставлено никакого алгоритма повторов, сообщения неудачны и немедленно шлётся рикошет, если почтовый ящик не читался по крайней мере 5 дней. Третье правило обрабатывает все другие ошибки wonderland.fict.example: повторы происходят каждые 15 минут в течение часа, затем с геометрически увеличивающимися интервалами до двух дней с момента первой ошибки доставки. После первого часа задержка один час, затем два часа, затем четыре часа и так далее (это в некоторой степени экстремальный пример). Четвёртое правило контролирует повторы для домена lookingglass.fict.example. Они происходят каждые 30 минут, только в течение 24 часов. Оставшиеся два правила обрабатывают все остальные домены со специальным действием при отказе в соединении для хостов, которые не были получены из MX-записей. Последнее правило в конфигурации всегда должно содержать звёздочки в первых двух полях для обеспечения общего правила для всех адресов, не имеющих собственной особой обработки. Этот пример, пробует каждые 15 минут в течение 2 часов, затем с интервалами, начинающимися с одного часа, и увеличивающимися путём фактора 1.5 до 16 часов, затем каждые 8 часов, вплоть до 5 дней.

32.8. Таймаут для данных повторов

Exim ставит метку времени на данные, которые пишет в базу подсказок повторов. Когда он консультируется с данными в течение доставки, он игнорирует любые данные, являющиеся более старыми, чем значение, установленное в retry_data_expire (по умолчанию 7 дней). Если, например, хост не проверялся в течение 7 дней, exim попробует доставить на него немедленно, по прибытию сообщения, и если это будет неудачным, он попробует вычислить время повтора, как будто была первая неудачная попытка доставки.

Это улучшает поведение для сообщений, направляющихся к редко используемым хостам, типа резервных MX. Если бы такой хост падал однажды, и такое случалось снова, когда exim пытался доставить на него, месяц спустя, то использование старых данных повторов подразумевало бы, что он лежит всё время, что не явялется верным предположением. Если хост действительно постоянно выключен, это поведение вызывает время от времени взрыв повторений, но лишь если направляющиеся к этому хосту сообщения редки. Если сообщения бывают по крайней мере раз в 7 дней, данные повтора никогда не истекут.

32.9. Долгосрочные ошибки

Когда адрес электронной почты был неудачен так долго, что истекло время уменьшения последнего алгоритма, происходит специальная обработка. Для примера, используем правило повтора по умолчанию:

* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
время уменьшения четыре дня. Достижение сокращения повтора не зависит от того, как долго любое специфическое сообщение будет неудачно: оно равно длине непрерывной ошибки для рассчитываемого адреса получателя. Когда истекает время уменьшения для локальной доставки или для всех IP-адресов, ассоциированных с удалённой доставкой, последующая ошибка доставки заставляет exim отказываться от адреса и генерировать рикошет. Для обслуживания новых сообщений, использующих неудачный адрес, следующее время повтора остаётся рассчитанным по конечному алгоритму и используется следующим образом:

Для локальных доставок для последующих сообщений всегда производится одна попытка доставки. Если эта доставка неудачна, адрес немедленно неудачен. Последующее время сокращения повторов не используется. Если доставка удалённая, есть два варианта, управляемых опцией delay_after_cutoff транспорта smtp. По умолчанию опция истинна.

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

Другими словами, когда все хосты для данного адреса электронной почты были неуспешны в течение долгого времени, exim срывает быстрее, чем задерживает, пока не достигнуто одно из времён повторов хостов. Тогда он пытается один раз и срывает, если попытка была безуспешной. Это поведение гарантирует, что при попытке доставить по кривому адресу будет затрачено немного ресурсов, но если хост восстановится, exim в конечном счёте это заметит. Если опция delay_after_cutoff установлена в ложь, exim ведёт себя по другому. Если все IP-адреса проходят их конечное время уменьшения, exim пробует доставить тем адресам, которые не пробовались с тех пор, как прибыло сообщение. Если нет подходящих адресов или все они неудачны, адрес срывается. Другими словами, он не задерживается по прибытии нового сообщения, а немедленно пытается доставить адреса с истёкшим сроком, если они не проверялись с момента прибытия сообщения.

Если существует непрерывный поток сообщений для неудачных доменов, установка delay_after_cutoff в ложь означает, что ещё будет намного больше попыток доставить на постоянно недоступные IP-адреса, чем когда delay_after_cutoff истина.

32.10. Доставки, работающие с перерывами

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

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

Для предотвращения этого случая применяются два необычных действия. Первое применяется к ошибкам, которые связаны с сообщением, а не с удалёнными хостами. В разделе 44.2 есть обсуждение различных видов ошибок, примеры связанных с сообщениями ошибок: ответы 4xx на команды MAIL или DATA и ошибки квоты. Для этого типа ошибок, если время прибытия сообщения более ранее, чем первое неудачное (first failed) время для ошибки, меньшее время используется при просмотре правил повторов, чтобы решить, когда проверять адрес, и когда таймаут адреса. Второе необычное действие применяется во всех случаях. Если сообщение было в очереди больше, чем время уменьшения для любого применимого правила для данного адреса, для этого адреса предпринимается доставка, даже если это не его время, а если эта доставка неудачна, происходит таймаут адреса. В этом случае новое время повтора адреса не вычисляется, таким образом, другие сообщения для того же самого адреса рассматриваются немедленно.