2008-09-30 7 views
37

네트워크 서버의 폴더 트리를보고 변경하려고합니다. 파일에는 모두 특정 확장자가 있습니다. 트리에는 약 200 개의 폴더가 있고 내가보고있는 확장자는 약 1200 개의 파일이 있습니다.네트워크 서버 폴더를 모니터링하는 System.IO.FileSystemWatcher - 성능 고려 사항

솔루션은 클라이언트에 로컬이어야하므로 서버에서 실행되는 서비스를 작성할 수 없습니다 (제한 없음!). 적시성은 특별히 중요하지 않습니다. 나는 알림에 1 분 또는 그 이상의 지연을두고 살 수 있습니다. 나는 창조, 삭제, 이름 바꾸기 및 변경을 지켜보고 있습니다.

.NET System.IO.fileSystemWatcher를 사용하면 서버에 많은 부하가 발생합니까?

시청중인 폴더/파일 수를 줄이기 위해 10 명의 개별 관찰자가 있습니까? (700 개의 폴더에서 200 개까지, 총 5500 개의 파일에서 1200 개까지) 더 적은 네트워크 트래픽이 아닌 더 많은 네트워크 트래픽? 내 생각은 감시 된 파일을 1 트리 아래에두기 위해 서버를 개편하는 것입니다. 나는 항상이 옵션을 가지고 있지 않을 수도있다.

FSW가 서버에 과도한로드를 생성하거나 sysadmin 유형의 전체적인 이유로 작동하지 않는 경우 다른 솔루션이 주기적으로 점검되는 것으로 가정합니다.

더 좋은 방법이 있나요?

답변

61

서버 부하 관점에서 설명하는 시나리오에서 원격 변경 알림을 위해 IO.FileSystemWatcher를 사용하면 아마도 가장 효율적인 방법 일 것입니다. 내부적으로 FindFirstChangeNotificationReadDirectoryChangesW Win32 API 함수를 사용하여 네트워크 리디렉터와 최적의 방식으로 통신합니다 (표준 Windows 네트워킹을 가정합니다. 타사 리다이렉터가 사용되고 필요한 기능을 지원하지 않으면 모든 것이 승리합니다. 전혀 일하지 않는다.) .NET 래퍼는 비동기 I/O 및 모든 것을 사용하므로 효율성을 극대화합니다.

이 솔루션의 유일한 문제점은 매우 신뢰할 수 없다는 것입니다. 일시적으로 네트워크 연결을 처리하는 것 외에도 IO.FileSystemWatcher가 처리 할 수있는 오류 이벤트를 발생시키기 때문에 문제가 많지는 않지만 기본 메커니즘에는 근본적인 제한 사항이 있습니다.는 Win32 API 함수에 대한 MSDN 문서에서 : 버퍼 길이가 64KB보다 큰이며, 응용 프로그램이 네트워크를 통해 디렉토리를 모니터링 할 때

  • ReadDirectoryChangesW는 ERROR_INVALID_PARAMETER 함께 실패합니다. 이 원격 파일 시스템 즉

에 대한 위해 FindFirstChangeNotification를 호출 할 때

  • 알림이 반환되지 않을 수 있습니다 기본 파일 공유 프로토콜 패킷 크기 제한으로 인해 : 높은 부하 (때 것 큰 버퍼가 필요함), 또는 불특정 무작위로 상황이 나빠지면 예상 한 통지를받지 못할 수도 있습니다. 이것은 로컬 파일 시스템 감시자와 관련한 문제이기는하지만 네트워크를 통해 훨씬 더 많은 문제가 있습니다. Another question here on SO은 API의 고유 한 신뢰성 문제에 대해 자세히 자세히 설명합니다.

    파일 시스템 감시자를 사용할 때 응용 프로그램은 이러한 제한 사항을 처리 할 수 ​​있어야합니다. 예를 들면 :

    • 당신이 찾고있는 파일 시퀀스 번호가있는 경우 향후 알림 '차이'에 대한보고를위한 파일을 처리 할 수 ​​있도록, 당신이에 대한 알림있어 마지막 시퀀스 번호를 저장하면 알리지 않았다.

    • 알림을 받으면 항상 전체 디렉토리 검색을 수행하십시오. 이것은 정말 좋지 않을 수도 있지만 스캔은 이벤트 기반이므로 벙어리 폴링보다 훨씬 효율적입니다. 또한, 스캔 할 디렉토리의 수와 함께 단일 디렉토리에있는 파일의 총 수를 1000 개 미만으로 유지하는 한이 작업의 성능에 미치는 영향은 최소화해야합니다. 여러 리스너를 설정

    당신은 가능한 한 피해야한다 뭔가 : 아무것도,이 일을 할 것입니다 경우에 당신이 절대적으로 이있는 경우에도 신뢰할 수있는 ...

    어쨌든, 사용하는 파일 시스템 감시자를 사용하면 제한 사항을 알고있는 한 정상적으로 작동하며 수정/생성 된 모든 파일에 대해 1 : 1 알림이 필요하지 않습니다.

    다른 옵션 (본질적으로 파일을 작성하는 프로세스가 파일 시스템이 아닌 방식으로 사용자에게 통지하는 경우 : 모든 일반 RPC 메소드가 개선 될 것입니다 ...), 이것들은 확실히 조사 할 가치가 있습니다 신뢰성의 관점에서.

  • -1

    FSW가있는 컴퓨터와 위치를 모니터링하는 컴퓨터 사이에 어떤 종류의 활성 상태 또는 통신이 있다고 생각하지 않습니다. 즉, FSW가 네트워크로 연결된 OS를 핑 (ping)하여 파일을 확인하지 않습니다.

    메시지 또는 이벤트가 변경되었을 때 만 제기되거나 네트워크 FSW로 전송되었다고 상상해보십시오.

    그러나 이것은 모두 추측입니다. :)

    +0

    핑 (ping)을하지 않으면 클라이언트가 서버에서 변경된 사항을 어떻게 알 수 있습니까? AFWIK FSW는 서버에서 어떤 프로세스도 시작하지 않습니다. 아직도 AFIK는이 경우별로 없습니다. –

    +1

    이제 답을 얻었으나 질문에 답할 수 있습니다. FSW는 파일 변경시 알림을 받고자하는 컴퓨터에 요청을 보냅니다. 잡지에 새로운 문제가 아직 없다면 계속 묻지 않고 한 번 구독하면 게시 될 때 새로운 문제가 발송됩니다. – core

    2

    MSDN documentation indicates FileSystemWatcher 구성 요소를 사용하여 네트워크상의 파일 시스템 변경 사항을 확인할 수 있습니다. 드라이브.

    또한 감시 프로그램 구성 요소가 대상 드라이브의 변경 사항을 주기적으로 확인하기보다는 파일 시스템 변경 알림을 수신하는 것을 나타냅니다.

    네트워크 트래픽의 양은 네트워크 드라이브 내용이 변경되는 정도에 따라 전적으로 좌우됩니다. FSW 구성 요소는 네트워크 트래픽 수준에 추가되지 않습니다.

    7

    저는 C#의 파일 시스템 감시자를 여러 번 사용했습니다. 처음 사용했을 때, 변경 사항을보고 한 스레드의 변경 사항을 처리 중이기 때문에 작업을 중단하는 데 문제가있었습니다.

    그러나 이제 큐에 변경 내용을 적용하고 다른 스레드에서 큐를 처리합니다. 이것은 내가 원래 가지고 있던 문제를 해결하는 것으로 보인다. 문제가 발생하면 여러 명의 관찰자가 동일한 대기열로 이동할 수 있습니다.

    그러나이 문제는 귀하의 문제 규모에 사용하지 않았습니다.

    3

    제 경험상 FSW는 높은 네트워크 트래픽을 생성하지 않습니다. 그러나 성능상의 문제가있는 경우 여러 명의 관찰자를 사용하고 감시되는 폴더 수가 줄어들면 합리적이라고 생각합니다.

    네트워크 드라이브의 FSW에는 몇 가지 큰 문제가있었습니다. 파일을 삭제하면 항상 삭제 된 이벤트가 아닌 오류 이벤트가 발생합니다. 솔루션을 찾지 못했기 때문에 FSW를 사용하지 마십시오 ...

    1

    감시자는 감시자 객체에서 버퍼 크기를 감시합니다. 수천 개의 파일 업데이트를 테스트했지만 잃어 버리지 않았습니다.

    멀티 스레드 방식을 사용하는 것이 좋습니다. - 파일 감시자가되는 트리거. 발견 된 각 파일 변경에 대해 스레드를 시작할 수 있습니다. 감시자는 오버플로 가능성이 훨씬 낮은 을 훨씬 빠르게 처리 할 수 ​​있습니다. (비동기 스레드 사용)

    +0

    로컬 파일 시스템에서 100 % 신뢰할 수있는 것처럼 보일 수 있지만 네트워크 공유에서는 신뢰할 수 없습니다. 공유를 제공하는 파일 서버가 튀어 오면 FSW는 뇌사 상태입니다. – DSoa

    1

    언젠가는 System.IO.FileSystemWatcher를 사용한 후. 너무 빨리 들어오는 이벤트를 처리 할만큼 안정적이지 않습니다. 파일을 100 % 읽도록 보장. 간단한 디렉토리 방법을 사용하여 파일을 검색합니다. 그것을 읽은 후 즉시 다른 폴더에 파일을 복사하십시오. 파일을 읽는 동안 추가되는 새 파일로부터 파일을 분리합니다.

    타이머는 폴더를 정기적으로 읽는 데 사용됩니다. 이미 읽은 파일을 보관 폴더로 복사하면 다시 읽지 않습니다. 이후의 읽기는 항상 새로운 파일입니다.

    var fileNames = Directory.GetFiles (srcFolder); foreach (fileName의 문자열 fileName) { string [] lines = File.ReadAllLines (fileName);