Архитектура с несколькими очередями, использующая systemd

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

awk -F/ '{ OFS="/"; print($2,$1,$3) }' ~/Downloads/Dates.csv

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

1
17.07.2019, 13:35
2 ответа

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

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

Я должен упомянуть одну сложность с этой файловой системой :возможно и даже вероятно, что файл все еще открыт для записи, когда он копируется в каталог IN. Блок пути срабатывает, когда файл появляется в каталоге, но процесс копирования еще не завершил запись в него. Это может привести к повреждению данных. Файл следует переместить или атомарно связать с каталогом IN, или следует использовать какой-либо другой механизм для опроса до тех пор, пока процесс копирования не закроет файл.

2
27.01.2020, 23:30

Думаю, мое первое замечание состоит в том, что вы используете термины «копировать», «синхронизировать» (rsync? )и "--удалить" (, что заставляет меня думать о rsync ), в то время как правильная реализация службы очередей, как вы описываете, должна беспокоиться о атомарности файлов в каждой очереди.

Предполагая, что у вас есть IN, PROCESSINGи OUT, управляемые вашим обработчиком очередей, вы должны использовать атомарные системные вызовы, такие как переименовать (2)и ссылка (2)(как в "жесткой ссылке" )для перемещения или дублирования/копирования файлов между несколькими очередями.

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

Способ решить эту проблему состоит в том, чтобы иметь дополнительный каталог, скажем, TMP, который не отслеживается системой очередей, но используется авторами для записи новых элементов. Писатели создавали там новый файл, заполняли его содержимым, закрывали файл и только затем использовали переименовать (2)или ссылку (2 ), чтобы переместить их в INочереди и сделать их доступными для процессора очереди, чтобы забрать их.

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

Что касается службы systemd, мне кажется, что вы можете обойтись одной службой systemd, выполняющей всю очередь, собирая элементы в IN, временно перемещая их в PROCESSINGи, наконец, выгружая их в OUT, когда Готово.

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

Да,использование чего-то вроде inotify может сделать это более эффективным, но на самом деле только тогда, когда очередь пуста, поскольку, когда она заполнена, вы будете запускать свои задания обратно -в -назад, как сразу после того, как закончите задания, вы повторно сканируете каталог, чтобы выбрать новое задание оттуда (, и inotify не может вам в этом помочь.)

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

Любое использование inotify чревато гонками. Что, если вы просканировали очередь и обнаружили, что она пуста, поэтому решили лечь спать. Но прямо перед тем, как вы это сделаете, в очередь добавляется новое задание, вызывающее уведомление. Но уведомление приходит до того, как вы решили заснуть, поэтому, поскольку вы все еще находились в режиме обхода очереди, вы решили, что уведомление не нужно, поэтому проигнорировали его? Это приводит к тому, что ваш процесс спит, пока есть элемент в очереди, и он не будет разбужен до тех пор, пока (или если когда-либо )другой элемент не будет поставлен в очередь.

Итак, дважды подумайте о введении inotify в картину (, будь то напрямую или через systemd path unit ), так как это довольно сложно и вам не обязательно иметь с этим дело, если вы можете опрос с достаточно большими интервалами.

Надеюсь, эти указатели будут вам полезны!

2
27.01.2020, 23:30

Теги

Похожие вопросы