外部エージェントによって定期的にアップロードされたファイルを確実に処理する方法は?
-
05-07-2019 - |
質問
これは非常に一般的なシナリオです。あるプロセスでは、30分ごとにサーバーにファイルをドロップしたいと考えています。シンプルでしょ?まあ、私はこれがうまくいかない多くの方法を考えることができます。
たとえば、ファイルの処理には30分以上かかる場合があるため、前のファイルを処理する前に新しいファイルが到着する可能性があります。ソースシステムが、まだ処理中のファイルを上書きしないようにします。
一方、ファイルは大きいため、アップロードが完了するまで数分かかります。部分的なファイルの処理を開始したくありません。ファイルはFTPまたはsftp(私の好み)で転送されるため、OSレベルのロックはオプションではありません。
最後に、ファイルの1つを手動で検査(デバッグ用)または再処理する必要がある場合に備えて、ファイルをしばらく保持する必要があります。
アップロードファイルをシャッフルしたり、ファイル名を交換したり、日付スタンプを使用したり、「インジケーター」に触れたりするためのアドホックなアプローチをたくさん見ました。同期を支援するファイルなど。まだ見たことがないのは、包括的な「アルゴリズム」です。並行性、一貫性、完全性に対処するファイルを処理するため。
だから、ここで群衆の知恵を活用したいと思います。バッチデータファイルをジャグリングする防弾の方法を誰もが見たことがあります。
解決
鍵は、送信の最後で最初のジャグリングを行うことです。送信者がする必要があるのは次のとおりです。
- 一意のファイル名でファイルを保存します。
- ファイルが送信されたらすぐに、たとえば、というサブディレクトリに移動します
completed
。
レシーバープロセスが1つしかない場合、レシーバーが行う必要があるのは次のとおりです。
- 定期的に
completed
ディレクトリでファイルをスキャンします。 - ファイルが
completed
に表示されたらすぐに、たとえば、というサブディレクトリに移動します。処理済み
、そこから作業を開始します。 - オプションで終了したら削除します。
正常なファイルシステムでは、同じファイルシステム/ボリューム内で発生するファイル移動はアトミックです。したがって、競合状態はありません。
複数のレシーバー
ファイルが配信される間隔よりも処理に時間がかかる可能性がある場合は、複数の受信プロセスがない限り、バックログを作成します。それでは、複数受信機のケースをどのように処理しますか?
シンプル:各受信プロセスは以前とまったく同じように動作します。重要な点は、ファイルを処理する前に processed
にファイルを移動しようとすることです。つまり、同じファイルシステムのファイルが移動することはアトミックであるということです。受信者は completed
で同じファイルを見て移動しようとしますが、成功するのは1つだけです。必要なのは、 rename()
の戻り値、または移動の実行に使用するOS呼び出しを確認し、成功した場合にのみ処理を続行することです。移動に失敗した場合、他の受信者が最初にそこに着いたので、戻って completed
ディレクトリをもう一度スキャンしてください。
他のヒント
OSがサポートしている場合は、ファイルシステムフックを使用して、ファイルのオープンおよびクローズ操作をインターセプトします。 Dazuko のようなもの。他のオペレーティングシステムでは、ファイル操作について別の方法で通知される場合があります。たとえば、Novell Open Enterprise Serverではエポックを定義でき、エポック中に変更されたファイルのリストを読み取ります。
Linuxでは、inotifyサブシステム、またはinotify-toolsパッケージのユーティリティを使用できることに気付きました
ファイル転送は、システム統合の古典の1つです。 エンタープライズ統合パターンブックを入手して、これらの質問に対する独自の回答を作成することをお勧めします。ある程度、答えはエンドポイントの実装とファイル転送に使用しているテクノロジーとプラットフォームによって異なります。実行可能なパターンの非常に包括的なコレクションであり、かなりよく書かれています。