
長期にわたって実行されるファイル処理を実行するサービスがあり、このサービスには一度に一度だけ使用できる処理用の特定のリソースが必要です。
ユーザーは日中にリソースを必要とするかもしれませんが、夜はそうではないかもしれません。日中、彼は同じことをしたり別のことをするためにそれを使うことができました。
ユーザーは夜に処理するファイルのリストもあり、いつでもこれらのファイルをキューフォルダに追加でき、夜に処理されます。
これを達成するために、私は次のことを行います。
フォルダ構造:
.
├── IN # user add files to be processed here
├── QUEUE # files that will be processed
├── PROCESSING # queue of size <= 1, contains the file being processed
├── OUT # when files have been processed, the service move them here
提供する:
# sync QUEUE with IN (possibly with --delete or not)
sync.service
# pick the oldest file from QUEUE and copy it to PROCESSING
pick_one.service
# process the file in PROCESSING,
# remove it from IN, QUEUE and PROCESSING when completed and move it to OUT
processing.service
パス単位:
sync.path # should trigger on each modification of IN folder
pick_one.path # should trigger while QUEUE is not empty and only when PROCESSING is
processing.path # should trigger whem a file is present in PROCESSING
時間制労働者:
start.timer # trigger sync.path and pick_one.path using a target ommitted here
stop.timer # stop sync.path and pick_one.path using a target ommitted here
IN
このシステムでは、ユーザーが夜に処理されるファイルをいつでも操作できることを願っています。私はユーザーがファイルを削除できるかどうか、まだ仲介者を使用してファイルをIN
処理できるかどうかを柔軟に選択できます。ユーザーが必要なファイルをフォルダーに配置するだけで、作業ができるように日中でも実行されます。QUEUE
sync.service
processing.path
PROCESSING
問題は、これを達成するためにパス単位で必要なオプションが見つからないことです。修正を監視できないか、IN
完了を待っているループを介してバッチ処理を回避できないようです。私は正しいですか?QUEUE
while QUEUE not empty
tune.service
while PROCESSING not empty
私はこのソリューションの柔軟性が好きですが、あまりにも複雑にすることも、私が試したように純粋なシステムでは不可能かもしれません。
私よりもプロポーズするより良い方法がある人はいますか?
ありがとう
PS:必要だと思えばユニットファイルの内容を投稿できますが、長すぎないようにできるだけ明確に投稿しようとしています。
答え1
ここでの最初の言及は、「コピー」、「同期化」(rsync?)、および「--delete」(これはrsyncについてさらに考える)という用語を使用することを見たことです。一方、キューの正しい実装はサービスです。説明することは問題になるはずです原子性各キューのファイル数。
キュープロセッサによって管理されるIN
、PROCESSING
およびがあると仮定すると、アトミックシステムコールを使用する必要があります。OUT
名前変更(2)そしてリンク(2)(例:「ハードリンク」)複数のキュー間でファイルを移動またはコピー/コピーします。
別の問題は、ファイルをキューに収集することです。キューに書き込むプロセスは、作業がIN
完了した後にのみディレクトリに入れるようにしてください。そうしないと、アトミック問題が再発生します(キュープロセッサがエントリを書き込むプロセスよりも速い場合は空のファイルが見つかります)。作成者がコンテンツを埋める時間があるまで)。
TMP
この問題に対する解決策は、キューシステムによって監視されないが、作成者が新しいエントリを保持するために使用する追加のディレクトリ(たとえば)を持つことです。作成者はそこに新しいファイルを作成し、内容を入力し、ファイルを閉じて使用します。名前変更(2)またはリンク(2)IN
これをキューに移動し、キュープロセッサからピックアップできるようにします。
2つの別々のキューが欲しいことはよくわかりませんIN
。QUEUE
おそらく私が言及したのと同じアイデアでしょうTMP
。しかし、2つのキュー間でアイテムを移動するバックグラウンドサービスについて話しましたが、焦点はTMP
プロセスと同期してアイテムを送信することです。これは解決すべき原子性問題であるからです。
IN
systemdサービスに関してキュー全体を実行し、その中の項目を選択し、一時的にここに移動し、タスクが完了すると最終的にダンプする単一のPROCESSING
systemdサービスでタスクを実行できるようです。OUT
キュージョブの処理時間とジョブを開始できる速度に応じて(待機時間にまったく気にする場合)、キュープロセッサがアイドル状態のときにディレクトリを定期的にポーリングするなど、非常に簡単なジョブで開始するIN
だけで十分です。あります。キューが空の場合は、5秒または60秒ごとにポーリングし、操作が完了するとすぐにポーリングを開始できます。したがって、キューが使用されている場合、ジョブは引き続き実行されます。
はい、次のようなものを使用してくださいinotifyより効率的ですが、実際にはキューが空の場合にのみ可能です。キューがいっぱいになると、ジョブは継続して実行されるためです。タスクが完了した後、そこから新しいタスクを選択するためにディレクトリを再検索することになるからです(inotifyは実際にはできません)。
inotifyを使用することを決定した場合は、デーモン自体で実装することができ、引き続き実行できますが、キューが空の場合はinotifyを登録し、エントリが配置されるとスリープモードになります。キューから目覚めます。またはあなたは使用することができますシステムパス単位、この場合、キューが空のときにサービスを終了し、処理する項目がある場合にのみsystemdにサービスを開始させることができます。
どちらにもinotifyを使用すると、潜在的な競争条件があります。キューをスキャンして空いていることを発見し、眠りにつくことにした場合はどうなりますか?ただし、これを実行する直前に新しいジョブがキューに追加され、通知がトリガーされます。しかし、あなたが眠りに落ちる前に通知が到着するので、それはまだキューウォークモードなので、通知は必要ないと仮定して無視しますか?これにより、キューに項目がある間にプロセスがスリープ状態になり、他の項目がキューに入るまで(または場合)実際には目が覚めません。
したがって、inotifyを画像にインポートすることを2回考えてください(直接またはシステムパス単位を介して)。これはかなりの複雑さをもたらし、かなり大きな間隔のクエリで実行できる場合は必ずしも処理する必要はありません。 。
この指示が役に立つことを願っています!
答え2
以下は、この問題を解決した方法の概要です。 INディレクトリのパスを使用してアクティブになり、タイマー(夜)で始まるサービスプログラムを作成します。サービスプログラムの作業は、INディレクトリでファイルを見つけ、見つかったすべてのファイルをQUEUEディレクトリに移動することです。そして(時間が合っている場合)ファイル操作を1つずつ開始します。プログラムはこれら2つの操作を交互に実行することも、別々のスレッドで並列に完了することもできます。
このシステムの主な原則は、プログラムが利用可能なすべてのタスクを実行して終了し、より多くのタスク(新しいファイル)があるとsystemdによって開始されることです。 systemdの機能は、目覚まし時計として機能し、実行する作業があるときにサービスを起動することです。サービス自体は、残りの作業量を確認し、終了する前に再確認する必要があります。
このファイルベースのシステムの1つの複雑な問題に言及する必要があります。ファイルがINディレクトリにコピーされると、ファイルはまだ書き込み用に開いている可能性があります。ファイルがディレクトリに表示され、コピープロセスで書き込みが完了していない場合は、パス単位が実行されます。これによりデータが破損する可能性があります。ファイルをINディレクトリに移動するか、アトミックにリンクする必要があります。それ以外の場合は、コピープロセスによってファイルが閉じられるまで、別のメカニズムを使用してポーリングする必要があります。