Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

GNU Mailman

Глава 10 из книги "Архитектура приложений с открытым исходным кодом", том 2.

Оригинал: GNU Mailman
Автор: Barry Warsaw
Перевод: А.Панин

10.4 Ведущий обработчик

При использовании всех описанных процессов обработчиков системе Mailman требуется простой способ их запуска и остановки; именно с этой целью был создан процесс ведущего обработчика, следящего за состоянием других обработчиков. У него должна быть возможность управления и обработчиками очередей, и обработчиками, которые не управляют очередями. Например, в версии 3 системы мы принимаем сообщения от используемого почтового сервера посредством протокола LMTP, который аналогичен протоколу SMTP, но позволяет выполнять только локальную доставку почтовых сообщений и, следовательно, может быть значительно упрощен, так как при его использовании не требуется обрабатывать нестандартные ситуации, возникающие в ходе доставки почты с использованием ненадежного соединения с Интернет. Обработчик протокола LMTP просто прослушивает порт, ожидая от используемого почтового сервера соединения и отправки байтового потока. После этого он преобразует этот байтовый поток в дерево объектов сообщения, создает начальный словарь метаданных и добавляет сообщение в обрабатываемую директорию очереди.

Система Mailman также использует обработчик, который прослушивает другой порт и обрабатывает REST-запросы, переданные по протоколу HTTP. Этот процесс вообще не затрагивает файлы очереди.

Стандартная работающая система Mailman может использовать восемь или десять процессов, причем все они должны быть остановлены и запущены корректно и согласованно. Они также могут внезапно аварийно завершаться; например, в случае, когда ошибка в Mailman приводит к неожиданному исключению. Когда это происходит доставляемое сообщение блокируется (shunted) и помещается в хранилище вместе с данными состояния системы в момент возникновения исключения, сохраненными в метаданных сообщения. Эта операция позволяет быть уверенным в том, что необработанное исключение не приведет к множеству повторных отправок сообщения. Теоретически администратор сайта, работающего под управлением системы Mailman, может устранить проблему, после чего разблокировать (unshunt) вызвавшие проблемы сообщения для повторной доставки с момента остановки процесса. После блокировки проблемного сообщения ведущий обработчик перезапускает аварийно завершивший работу обработчик очереди, который начинает обработку оставшихся сообщений из своей очереди.

При запуске ведущий обработчик исследует файл конфигурации для установления того, какое количество и какие типы дочерних обработчиков должны быть запущены. В случае обработчиков для поддержки протоколов LMTP и REST обычно используется по одному процессу. В случае обработчиков очередей, как было сказано выше, может быть запущено кратное двум количество параллельно выполняющихся процессов. Ведущий обработчик использует вызовы fork() и exec() для запуска всех обработчиков, необходимость которых заявлена в файле конфигурации, передавая соответствующие параметры командной строки каждому из них (т.е., указывая подпроцессу на то, с каким диапазоном хэш-значений ему следует работать). После этого ведущий обработчик блокируется в бесконечном цикле, ожидая завершения работы одного из своих дочерних процессов. Он отслеживает идентификаторы каждого из дочерних процессов вместе с количеством перезапусков каждого дочернего процесса. Этот подсчет позволяет избежать катастрофической ошибки, приводящей к непрерывному каскаду перезапусков. Существует переменная конфигурации, которая устанавливает разрешенное количество перезапусков, по истечении которого сообщение об ошибке заносится в системный журнал и обработчик больше не перезапускается.

При завершении работы дочернего процесса ведущий обработчик рассматривает код завершения процесса и сигнал, с помощью которого был завершен подпроцесс. Каждый процесс обработчика устанавливает функции обработки сигналов со следующими семантиками:
  • SIGTERM: умышленное завершение подпроцесса. Перезапуск не должен производиться. Сигнал SIGTERM является тем сигналом, который отправляется процессом init для завершения работы процессов при изменении уровней выполнения, а также является тем сигналом, который отправляет система Mailman для завершения работы подпроцесса.
  • SIGINT: также используется для умышленного завершения подпроцесса и является тем сигналом, который используется при использовании сочетания клавиш control-C в командной оболочке. Обработчик не перезапускается.
  • SIGHUP: сообщает процессу о необходимости закрытия и повторного открытия файлов журнала без прерывания работы. Сигнал используется для ротации файлов журнала.
  • SIGUSR1: изначальная остановка подпроцесса с разрешением его перезапуска ведущим обработчиком. Используется для реализации команды restart сценариев инициализации.

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

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

Таким образом, мы переходим к заключительной части описания ведущего обработчика, а именно, описанию его интерфейса командной строки. Сам сценарий ведущего обработчика может принимать очень малое количество параметров командной строки. Этот сценарий, как и сценарии обработчиков очередей, умышленно упрощены. Это утверждение не было справедливым при рассмотрении версии 2 системы Mailman, в которой сценарий ведущего обработчика был достаточно сложен и пытался выполнять большое количество действий, что в большей степени затрудняло его понимание и отладку. В версии 3 системы Mailman реальный интерфейс командной строки для ведущего обработчика находится в сценарии bin/mailman, являющимся типом мета-сценария и содержащим множество подкоманд, оформленных в стиле, набравшем популярность вместе с такими программами, как Subversion. Это решение позволяет сократить количество программ, которые должны быть установлены в директорию, заданную переменной PATH вашей оболочки. В сценарии bin/mailman имеются подкоманды для запуска, остановки и перезапуска ведущего обработчика, также, как и всех его подопроцессов, а также команды для принудительного повторного открытия всех файлов журналов. Подкоманда start использует вызовы функций fork() и exec() процессом ведущего обработчика, в то время, как все остальные просто отправляют соответствующий сигнал ведущему серверу, который затем распространяет этот сигнал среди своих подпроцессов, как описано выше. Это улучшенное разделение ответственности упрощает понимание роли каждого отдельного программного компонента.


Далее: Правила, звенья и цепочки