Процесс Python как правильный демон (и, возможно, Windows Service)

Я реализую программу, которая работает 24/7. Он непрерывно выполняет задачи каждые 15 секунд или около того, однако для выполнения некоторых задач может потребоваться произвольное время (более 15 секунд), и не рекомендуется выполнять другие операции на том же работнике, когда он выполняет задачу (некоторые задачи включают развертывание и устранение экземпляров виртуальных машин). Выполнение этого с помощью cronjob без сохранения состояния потребует сложной логики блокировок, которая вряд ли будет масштабируема, поэтому это не вариант.

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

Прямо сейчас все программное обеспечение реализовано в виде подкласса многопоточности. При этом все аспекты параллелизма уже решены.

Конечная точка системы - это ОЧЕНЬ ПРОСТОЙ скрипт, который считывает конфиги из аргументов и файлов и инициализирует поточный класс с помощью ʻem. После этого он запускает метод start() и ждет бесконечно, перезапуская основной класс в случае сбоя.

Что я хочу сделать, так это реализовать этот простой класс как хорошо управляемый процесс демона (сейчас я использую nohup и &, чтобы добиться цели) с помощью start/stop И простого метода состояния, который печатает информацию о запущенных заданиях, размере текущего кластера и т. д., весь простой текст. Прямо сейчас у меня есть прослушиватель сигналов, который эмулирует stop() и status(), изящно останавливая потоки (при необходимости) и печатая вывод в файл.

Удаленный кластер и его логика связи / расписания - это пользовательская реализация, использующая Pyro4, поэтому одним из вариантов будет регистрация самого основного процесса в Pyro Daemon, поэтому одной из альтернатив будет регистрация самого класса daemonizable и использование некоторого пользовательского кода Python для подключиться к нему и получить статус, однако, я думаю, что это излишне и полагается на пиро-демона, который добавляет ненужные точки отказа в систему.

Я наткнулся на несколько библиотек, которые утверждают, что создают правильных демонов:

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

Все это касается демонов linux, однако, есть ли какой-нибудь ПРОСТОЙ класс, который обрабатывает службы Windows, а также демоны linux? Моя текущая программа предназначена только для Linux из-за других внешних ограничений, но в будущем было бы неплохо избежать программирования двух разных веток.

Для моего текущего проекта мне не нужно ничего, кроме описанного выше, однако, думая о будущем, я хотел бы иметь возможность ОТПРАВИТЬ некоторую информацию С терминала на демонов. Ничего сложного, просто команды с простой строковой / числовой информацией в качестве аргументов.

Например, было бы неплохо иметь функцию "reload_config", которая позволяет мне передавать новое местоположение файла конфигурации из консоли. Прямо сейчас, чтобы перезагрузить конфигурацию, я изменяю конфигурационный файл CURRENT и приказываю процессу прочитать его снова, используя сигнал. Это уменьшает выполнимые функции, которые могут быть реализованы с использованием этого (вы можете использовать временный файл в известном месте, чтобы сохранить команду и заставить ее прочитать ее, но это тоже не чистое решение)

Насколько я знаю, единственными правильными способами достижения этого (помимо использования файла связи) являются:

  • TCP-сокет прослушивания в потоке, который слушает команды, отправленные с помощью специального клиента. Это вводит проблемы безопасности и вынуждает вас создавать некоторую нехватку грамматики, которая позволяет вам представлять ваши команды наиболее эффективным способом, и добавляет проблемы связи.
  • Простой веб-сервер на Python, действующий как посредник с заказами: клиент публикует на веб-сервере, и поток получает оттуда. Сейчас кажется, что с безопасностью легче справиться, чем в предыдущем случае (https избавляет от необходимости заботиться о шифровальных атаках и атаках типа "человек посередине"), но это все еще проблема.
  • Использование Pyro4 для удаленной загрузки класса при необходимости с управляющих клиентов, что мне кажется слишком грязным.
  • Использование "коммуникационного файла" для получения / отправки сложных данных в процесс. Это выглядит грязно и совершенно не соответствует современному уровню техники.

** ПРИМЕЧАНИЕ. В настоящее время я использую logging.Logger для непосредственного входа в файл. Может ли это быть проблемой? Насколько я знаю (и думаю) это не так, но вы никогда не знаете...

Кроме того, согласно первому ответу этого поста, "systemd делает многие демоны устаревшими", я не очень привык к systemd (неохотно переходил на современные ОС, пока не смог больше его откладывать), однако, с помощью этого метода я могу просто сделать то, что делаю сейчас: перехватывать и корректно обрабатывать сигналы закрытия и автоматически запускать / убивать скрипт из systemd, что кажется недостаточным.

Хотя кажется, что если я не реализую более сложные клиент / серверы, я не смогу отправлять команды с аргументами своим службам, я ошибаюсь? Идеальная ситуация - запускать такие команды:

systemctl custom_command python_service custom_argument

хотя я не думаю, что systemd поддерживает что-то подобное, я не прав?

В любом случае, для решения основных вопросов этих возможностей будет достаточно:

systemctl start python_service 
systemctl stop python_service 
systemctl restart python_service 
systemctl reload python_service 
systemctl status python_service 

1 ответ

Я думаю, что вы в первую очередь спрашиваете:

Есть ли простой класс, который обрабатывает службы Windows, а также демоны Linux?

Поскольку эти два очень разные, я думаю, что ответ должен быть: нет.

Любой класс, который обрабатывал бы оба из них, был бы довольно сложным по определению.

Другие вопросы по тегам