簡體   English   中英

FTP如何不斷傳入文件

[英]How to FTP constantly incoming files

好的,情況就是這樣……我有一個每秒生成大約 8 個文件的應用程序。 每個文件為 19-24kb。 這會每分鍾生成大約 10 到 11 MB。 這個問題不是關於如何 ftp,因為我已經有了那個解決方案......問題更多的是關於如何跟上數據流(在大多數情況下只有 2mb 的上傳帶寬,除非我正在前往客戶端站點有一個大管道)。 我不在乎 ftp 的傳輸時間是否比流速更長,但我想知道是否有人知道如何批處理文件以移動它們,以便在 ftp 進程完成時,它將只刪除它傳輸的那些文件然后繼續下一批。 這是我的想法:

應用程序多線程,第一個線程運行應用程序,第二個線程是一個計時器,它每“N”分鍾創建一個文本文件,其中包含在該時間跨度內創建的所有文件。 StreamRead文件並將文本中的文件移動到另一個位置(可能創建一個臨時文件夾),然后ftp這些文件,然后刪除文件,文件夾和文本文件......同時,更多的文本文件正在寫入和臨時正在創建的文件夾。 這聽起來可行嗎? 我會接受任何人的建議,只是尋找最快和最可靠的路徑。

請不要要求查看代碼,考慮到我們正在處理假設,沒有理由看到它。

我會創建一個服務並使用 FileSystemWatcher、System.Threading.Timer 或兩者將傳入的文件添加到並發集合中(如果 FileSystemWatcher 的緩沖區溢出,它可能會丟失文件,因此最好有一個計時器來獲取任何文件錯過了)。 當文件進入時,我會將它們移動到一個單獨的文件夾中,並使用 .NET 4.0 任務處理它們。 然后,我將在原始任務的后續步驟中進行任何必要的后期處理。 您可以擁有處理任何故障的延續步驟和成功時發生的不同延續步驟。 這些任務中的每一個都將在線程池中啟動一個線程並為您管理。

以下是來自 OnlyOnFaulted 延續任務的http://msdn.microsoft.com/en-us/library/dd997415.aspx的示例。 您可以有第二個延續任務,只有在成功時才會運行。

var task1 = Task.Factory.StartNew(() =>
{
    throw new MyCustomException("Task1 faulted.");
})
.ContinueWith((t) =>
    {
        Console.WriteLine("I have observed a {0}",
            t.Exception.InnerException.GetType().Name);
    },
    TaskContinuationOptions.OnlyOnFaulted);

如果真的不知道為什么需要將所有工作保留在單個應用程序中並處理線程復雜性的更多細節,人們可能會爭辯將生成文件的部分和 FTP 文件的部分保留在單獨的應用程序中。

責任分離。 確保每個應用程序只完成一項工作,並且正確且快速地完成。

一個服務或應用程序(桌面/網絡)生成文件。

另一個監視文件夾並將任何傳入文件移動到臨時文件的服務,執行它需要做的事情,FTP 和刪除。

看到我不知道您的設置以及您從哪里獲取文件內容,將其寫入單個應用程序可能是您所建議的最佳選擇。

基本上回答你的問題。 是的,你想做的事情聽起來確實可行。 您如何實施它以及您對實施的滿意程度取決於您。

如果您在實施過程中遇到問題,請隨時在新威脅中發布任何問題,並附上一些代碼示例,說明您如何實施特定功能以及遇到的問題。

在那之前,假設您認為能夠管理您需要實現的目標的任何方法都是完全有效的。

編輯

看到您說您已經完成了生成文件的應用程序,並且您已經有了一個解決方案,FTP 意味着使用 2 個單獨的應用程序聽起來更合理。

然后,您所需要的只是圍繞 FTP 解決方案和快樂的日子提供服務。 如果它已經在工作,則無需干擾生成文件的原始應用程序。

為什么要冒險破壞它,除非您必須在其中添加 fTP 功能並且您別無選擇。

我在以前的工作中從事過類似的工作。 我將外部進程轉儲文件放在某個文件夾上。 這是我遵循的算法:

  1. 在轉儲文件的源目錄上運行 FileSystemWatcher
  2. 找到新文件后,按日期升序處理目錄中的所有文件。 (在你的情況下 ftp 文件)
  3. 處理文件后,我將它們移動到 Processed 目錄(在您的情況下,您可以刪除它們)

需要考慮的事項:

  1. 我可以有多少個打開的 ftp 連接/處理線程
  2. FileSystemWatcher 可以並且將在處理另一個文件時引發事件。 如何處理它/將它發送到適當的線程

如果生產者太快,您需要在文件的生產者和消費者(FTP 主機)之間插入一個隊列,以便能夠緩沖文件。 這需要某種形式的多線程甚至多個進程。

您提出了一個解決方案,其中隊列是文件系統,這很有可能,但在許多情況下並不理想。 您必須正確鎖定以避免傳輸半滿或空文件等。如果您決定使用文件系統,我的經驗是FileSystemWatcher不能用於此目的。 使用計時器運行任務,例如每秒拾取新文件更可靠。

其他隊列技術可能是內存隊列(但您必須考慮如何處理崩潰)、私有 Microsoft 消息隊列或 SQL 服務器代理隊列。 最佳解決方案很大程度上取決於您的要求。

FTP 不是真正的事務性隊列,您可能決定使用非事務性隊列(MSMQ 和 SQL 服務器代理都是事務性的),但您仍然應該嘗試圍繞創建文件、排隊的事務的概念構建應用程序並交付。 如果無法交付,則將其留在隊列中,稍后重試交付。 如果它不能被排隊,生產者應該重試排隊等等。你不想要一個文件永遠不會被傳遞或被傳遞兩次的情況。

從您的問題中不清楚您將如何使用 FTP,但我建議您使用開源或商業庫直接能夠從您的應用程序中使用 FTP,而不是使用ftp.exe 這將允許您的應用程序智能地保持 FTP 連接打開以避免過度重新連接等。

您還應該考慮如何處理隊列增長過大的情況。 一種選擇可能是停止生產者,直到隊列大小減少到閾值以下。

  1. 啟動一個每秒觸發一次的計時器。
  2. 在計時器的經過事件處理程序中,停止計時器。
  3. 獲取傳入目錄中所有文件的列表。
  4. 嘗試以獨占方式打開每個文件。 這可以防止您讀取仍在寫入的文件。
  5. 將每個文件復制到暫存目錄並將其從傳入目錄中刪除。
  6. 移動列表中的所有文件后,通過 FTP 發送暫存目錄中的文件。
  7. 將文件通過 FTP 傳輸后,將它們從暫存目錄中刪除。
  8. 啟動計時器。

計時器的經過處理程序在線程池上為您運行,您應該需要任何更高級的線程管理。 由於您的主要限制是您的 FTP 帶寬,因此在上傳文件之前與其他線程做任何其他事情幾乎沒有優勢。

這種方法可以在系統崩潰時為您提供保護。 暫存目錄中未發送的文件將在下一個周期中提取。 傳入目錄中的文件也是如此。

如果您的 FTP 接收端可以處理壓縮文件,您將通過壓縮暫存目錄的內容並將其作為一個文件發送來提高吞吐量。

我會使用 BlockingCollections 建立一個線程鏈。

一個生產者線程使用計時器或 FileSystemWatcher 等讀取可用文件,並將它們存儲在 BlockingCollection 中。 它還將文件存儲在一個列表中,以確保它們只添加一次。

var availableFiles = new BlockingCollection<string>();
var processedFiles = new BlockingCollection<string>();
var newFiles = new HashSet<string>();

...
lock (newFiles) {
    foreach (var file in Directory.GetFiles())
        if (!newFiles.Contains(file)) {
            availableFiles.Add(file);
            newFiles.Add(file);
        }
}

一個或多個 ftp 線程發送文件,然后將它們放入已處理的集合中

foreach (var file in availableFiles.GetConsumingEnumerable()) {
   SendFileOverFtp(file);
   processedFiles.Add(file);
}

一個線程清理處理過的文件

foreach (var file in processedFiles.GetConsumingEnumerable()) {
    lock (newFiles) {
       File.Delete(file);
       newFiles.Remove(file);
    }
}

另一種選擇是讓生產線程也將文件讀入 memory 並刪除它們。 在這種情況下,您可以跳過最后一個階段和 newFiles 集合

作為在這種情況下的 FTP 服務器所有者,我還要求您找到一種盡可能保持登錄狀態的方法。

登錄/注銷通常比單個文件傳輸更“昂貴”(在計算、配置阻塞等方面)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM