webdevqa.jp.net

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

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

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

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

監視されているフォルダー/ファイルの数を減らすために、10人の別々のウォッチャーはどうですか? (700フォルダーから200、合計で5500ファイルから1200)ネットワークトラフィックを減らすのではなく、増やすのですか?私の考えは、監視されたファイルを1つのツリーの下に配置するためにサーバーを改造することです。私はいつもこのオプションを持っているわけではないので、ウォッチャーのチームです。

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

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

41
CAD bloke

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

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

  • ReadDirectoryChangesW バッファー長が64 KBを超え、アプリケーションがネットワーク経由でディレクトリを監視している場合、ERROR_INVALID_PARAMETERで失敗します。これは、基になるファイル共有プロトコルのパケットサイズ制限が原因です。

  • リモートファイルシステムに対して FindFirstChangeNotification を呼び出すと通知が返されない場合がある

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

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

  • 探しているファイルにシーケンス番号がある場合は、通知を受けた最後のシーケンス番号を保存してください。そうすれば、将来の通知で「ギャップ」を探して、通知を受けていないファイルを処理できます。

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

複数のリスナーを設定することは、できる限り避けなければなりません。どちらかと言えば、これにより状況が均一になります もっと少なく 信頼性のある...

とにかく、絶対に 持ってる ファイルシステムウォッチャーを使用するには、制限を認識している限り、問題なく機能し、変更/作成されたすべてのファイルに対して1対1の通知を期待しません。

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

71
mdb

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

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

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

9
Nick Randell

私の経験では、FSWは高いネットワークトラフィックを生み出しません。ただし、パフォーマンスの問題がある場合は、複数のウォッチャーを使用して、監視対象のフォルダーを少なくするというアプローチが合理的です。

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

3
Treb

MSDNのドキュメントに示されています FileSystemWatcherコンポーネントを使用して、ネットワークdrive上のファイルシステムの変更を監視できます。

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

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

2
Jim Burger

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

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

1
davidWazy

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

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

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