ネットワークサーバーフォルダーを監視するSystem.IO.FileSystemWatcher-パフォーマンスの考慮事項

StackOverflow https://stackoverflow.com/questions/151804

質問

ネットワークサーバー上のフォルダーツリーの変更を監視したい。ファイルにはすべて特定の拡張子が付いています。ツリーには約200個のフォルダーと、私が見ている拡張子を持つ約1200個のファイルがあります。

サーバー上で実行するサービスを書くことはできません(立ち入り禁止です!)ので、ソリューションはクライアントに対してローカルでなければなりません。適時性は特に重要ではありません。通知が1分以上遅れて生きることができます。作成、削除、名前変更、変更を監視しています。

.NET System.IO.fileSystemWatcherを使用すると、サーバーに大きな負荷がかかりますか?

監視対象のフォルダ/ファイルの数を削減するために、10人の独立した監視者はどうですか? (700個のフォルダーから200個まで、合計で5500個のファイルから1200個まで)私の考えは、監視されたファイルを1つのツリーの下に置くためのサーバーの改造です。常にこのオプションがあるとは限らないため、ウォッチャーのチームがあります。

他の解決策は、FSWがサーバーに不当な負荷をかけるか、SysAdminタイプの理由で機能しない場合の定期的なチェックだと思います。

これを行うより良い方法はありますか?

役に立ちましたか?

解決

サーバー負荷の観点から、 IOを使用して説明するシナリオでのリモート変更通知の.FileSystemWatcher は、おそらく最も効率的な方法です。 FindFirstChangeNotification および ReadDirectoryChangesW Win32 API関数は内部で最適化された方法でネットワークリダイレクタと通信します(標準のWindowsネットワークを想定) :サードパーティのリダイレクタが使用されており、必要な機能をサポートしていない場合、まったく機能しません)。 .NETラッパーは、非同期I / Oとすべてを使用して、最大効率をさらに保証します。

このソリューションの唯一の問題は、信頼性があまり高くないことです。 IO.FileSystemWatcherはエラーイベントを発生させるため、一時的にネットワーク接続を一時的に切断する必要があります(この場合、処理できるエラーイベントが発生するため)、根本的なメカニズムには特定の基本的な制限があります。 Win32 API関数のMSDNドキュメントから:

言い換えると、高負荷(大きなバッファが必要な場合)であるか、さらに悪いことに、ランダムな不特定の状況では、期待する通知が得られない場合があります。これはローカルファイルシステムウォッチャーの問題でもありますが、ネットワーク上でははるかに大きな問題です。 SOに関する別の質問では、APIに固有の信頼性の問題をもう少し詳しく説明しています。

ファイルシステムウォッチャーを使用する場合、アプリケーションはこれらの制限に対処できる必要があります。例:

  • 探しているファイルにシーケンス番号がある場合は、通知された最後のシーケンス番号を保存します。これにより、今後の通知で「ギャップ」を探し、取得していないファイルを処理できます通知;

  • 通知を受け取ったら、常にディレクトリ全体のスキャンを実行します。これは本当に悪いように聞こえるかもしれませんが、スキャンはイベント駆動型であるため、ダムポーリングよりもはるかに効率的です。また、スキャンするディレクトリの数だけでなく、1つのディレクトリにファイルの総数を保持する限り、この操作がパフォーマンスに与える影響はとにかく最小限に抑えられます。

複数のリスナーを設定することは、できる限り避けるべきです:どちらかといえば、これは less の信頼性をさらに高めます...

とにかく、ファイルシステムウォッチャーを絶対に使用する 場合、制限を認識していれば問題なく動作し、変更されたすべてのファイルについて1対1の通知を期待しないでください。 /作成した。

したがって、他のオプションがある場合(基本的に、ファイルを書き込むプロセスに非ファイルシステムベースの方法で通知する:通常のRPCメソッドは改善されます...)、それらは間違いなく検討する価値があります信頼性の観点。

他のヒント

C#のファイルシステムウォッチャーを何度も使用しました。初めてそれらを使用したとき、主に変更を報告したスレッドで変更を処理していたという事実のため、動作を停止する問題がありました。

ただし、変更をキューにプッシュし、別のスレッドでキューを処理します。これは私が最初に持っていた問題を解決するようです。問題については、複数のウォッチャーが同じキューにプッシュすることができます。

しかし、私はあなたの種類の問題の規模でこれを使用していません。

私の経験では、FSWは高いネットワークトラフィックを生成しません。ただし、パフォーマンスに問題がある場合は、複数のウォッチャーを使用して、ウォッチ対象のフォルダーをより少ないフォルダーに分割するというアプローチが妥当であると思われます。

ただし、ネットワークドライブ上のFSWには大きな問題がいくつかありました。ファイルを削除すると、常にエラーイベントがスローされ、削除されたイベントはスローされませんでした。解決策が見つからなかったので、回避策がある場合はFSWの使用を避けるようにしました...

MSDNドキュメントが示している FileSystemWatcherコンポーネントを使用して、ネットワーク上のファイルシステムの変更を監視できるドライブ

また、監視コンポーネントが定期的にターゲットドライブに変更を問い合わせるのではなく、ファイルシステムの変更通知をリッスンすることを示します。

それに基づいて、ネットワークトラフィックの量は、そのネットワークドライブの内容がどれだけ変化すると予想されるかに完全に依存します。 FSWコンポーネントはネットワークトラフィックのレベルに追加しません。

ウォッチャーは100%信頼できるように見えます-ウォッチャーオブジェクトのバッファーサイズを監視するだけです。 何千ものファイル更新をテストしましたが、どれも失われませんでした。

マルチスレッドアプローチの使用をお勧めします-トリガーはFile Watcherです。 検出されたファイル変更ごとにスレッドを起動できます。ウォッチャーははるかに高速に処理できます オーバーフローの可能性が低くなります。 (非同期スレッドを使用)

System.IO.FileSystemWatcherをしばらく使用した後。速すぎるイベントを処理するには、十分に安定していません。ファイルの100%読み取りを保証するため。単純なディレクトリメソッドを使用して、ファイルを検索します。読んだ後、すぐにファイルを別のフォルダにコピーします。ファイルの読み取り中に追加される新しいファイルから分離するため。

タイマーは、フォルダーを定期的に読み取るために使用されます。既に読み取られたファイルをアーカイブフォルダーにコピーすることにより、これが再度読み取られないようにします。その後の読み取りは常に新しいファイルになります。

var fileNames = Directory.GetFiles(srcFolder);
foreach (string fileName in fileNames)
{
   string[] lines = File.ReadAllLines(fileName);
}

FSWがインストールされているコンピューターと、場所が監視されているコンピューターとの間にアクティブな状態や通信が存在するとは思わないでしょう。言い換えれば、FSWはネットワークOSにpingを送信してファイルをチェックしていません。

変更が発生したときに、メッセージまたはイベントは only でネットワーク化されたFSWにのみ発生/送信されると想像できます。

しかし、これはすべて推測にすぎません。 :)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top