systemdを使用したマルチキューアーキテクチャ

systemdを使用したマルチキューアーキテクチャ

長期にわたって実行されるファイル処理を実行するサービスがあり、このサービスには一度に一度だけ使用できる処理用の特定のリソースが必要です。

ユーザーは日中にリソースを必要とするかもしれませんが、夜はそうではないかもしれません。日中、彼は同じことをしたり別のことをするためにそれを使うことができました。

ユーザーは夜に処理するファイルのリストもあり、いつでもこれらのファイルをキューフォルダに追加でき、夜に処理されます。

これを達成するために、私は次のことを行います。

フォルダ構造:

.
├── 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処理できるかどうかを柔軟に選択できます。ユーザーが必要なファイルをフォルダーに配置するだけで、作業ができるように日中でも実行されます。QUEUEsync.serviceprocessing.pathPROCESSING

問題は、これを達成するためにパス単位で必要なオプションが見つからないことです。修正を監視できないか、IN完了を待っているループを介してバッチ処理を回避できないようです。私は正しいですか?QUEUEwhile QUEUE not emptytune.servicewhile PROCESSING not empty

私はこのソリューションの柔軟性が好きですが、あまりにも複雑にすることも、私が試したように純粋なシステムでは不可能かもしれません。

私よりもプロポーズするより良い方法がある人はいますか?

ありがとう

PS:必要だと思えばユニットファイルの内容を投稿できますが、長すぎないようにできるだけ明確に投稿しようとしています。

ベストアンサー1

ここでの最初の言及は、「コピー」、「同期化」(rsync?)、および「--delete」(これはrsyncについてさらに考える)という用語を使用することを見たことです。一方、キューの正しい実装はサービスです。説明することは問題になるはずです原子性各キューのファイル数。

キュープロセッサによって管理されるINPROCESSINGおよびがあると仮定すると、アトミックシステムコールを使用する必要があります。OUT名前変更(2)そしてリンク(2)(例:「ハードリンク」)複数のキュー間でファイルを移動またはコピー/コピーします。

別の問題は、ファイルをキューに収集することです。キューに書き込むプロセスは、作業がIN完了した後にのみディレクトリに入れるようにしてください。そうしないと、アトミック問題が再発生します(キュープロセッサがエントリを書き込むプロセスよりも速い場合は空のファイルが見つかります)。作成者がコンテンツを埋める時間があるまで)。

TMPこの問題に対する解決策は、キューシステムによって監視されないが、作成者が新しいエントリを保持するために使用する追加のディレクトリ(たとえば)を持つことです。作成者はそこに新しいファイルを作成し、内容を入力し、ファイルを閉じて使用します。名前変更(2)またはリンク(2)INこれをキューに移動し、キュープロセッサからピックアップできるようにします。

2つの別々のキューが欲しいことはよくわかりませんINQUEUEおそらく私が言及したのと同じアイデアでしょうTMP。しかし、2つのキュー間でアイテムを移動するバックグラウンドサービスについて話しましたが、焦点はTMPプロセスと同期してアイテムを送信することです。これは解決すべき原子性問題であるからです。

INsystemdサービスに関してキュー全体を実行し、その中の項目を選択し、一時的にここに移動し、タスクが完了すると最終的にダンプする単一のPROCESSINGsystemdサービスでタスクを実行できるようです。OUT

キュージョブの処理時間とジョブを開始できる速度に応じて(待機時間にまったく気にする場合)、キュープロセッサがアイドル状態のときにディレクトリを定期的にポーリングするなど、非常に簡単なジョブで開始するINだけで十分です。あります。キューが空の場合は、5秒または60秒ごとにポーリングし、操作が完了するとすぐにポーリングを開始できます。したがって、キューが使用されている場合、ジョブは引き続き実行されます。

はい、次のようなものを使用してくださいinotifyより効率的ですが、実際にはキューが空の場合にのみ可能です。キューがいっぱいになると、ジョブは継続して実行されるためです。タスクが完了した後、そこから新しいタスクを選択するためにディレクトリを再検索することになるからです(inotifyは実際にはできません)。

inotifyを使用することを決定した場合は、デーモン自体で実装することができ、引き続き実行できますが、キューが空の場合はinotifyを登録し、エントリが配置されるとスリープモードになります。キューから目覚めます。またはあなたは使用することができますシステムパス単位、この場合、キューが空のときにサービスを終了し、処理する項目がある場合にのみsystemdにサービスを開始させることができます。

どちらにもinotifyを使用すると、潜在的な競争条件があります。キューをスキャンして空いていることを発見し、眠りにつくことにした場合はどうなりますか?ただし、これを実行する直前に新しいジョブがキューに追加され、通知がトリガーされます。しかし、あなたが眠りに落ちる前に通知が到着するので、それはまだキューウォークモードなので、通知は必要ないと仮定して無視しますか?これにより、キューに項目がある間にプロセスがスリープ状態になり、他の項目がキューに入るまで(または場合)実際には目が覚めません。

したがって、inotifyを画像にインポートすることを2回考えてください(直接またはシステムパス単位を介して)。これはかなりの複雑さをもたらし、かなり大きな間隔のクエリで実行できる場合は必ずしも処理する必要はありません。 。

この指示が役に立つことを願っています!

おすすめ記事