0

我在寫一個使用boost :: asio的Http服務器。對於大文件,爲了避免將整個文件讀入內存併發送到網絡,我使用boost :: asio :: async_write在網絡上發送了部分文件。boost :: async_write大文件和內存消耗

問題是我的生產者(從文件中讀取的函數)比消費者(boost :: asio :: async_write)快得多,這導致了大文件的巨大內存消耗。

我想通過限制緩衝區列表來避免這個問題。這似乎是一個簡單的生產者/消費者問題,但是,我不想在這樣做時阻止一個線程。

我使用boost :: io_service和n個線程的線程池,這個線程池是可配置的,如果我們對大文件有太多的請求,我不想以不再服務任何請求的服務器結束。

所以我的問題是: - 我怎樣才能設計這個機制,而不阻塞線程? - 我是否應該測試列表大小,然後如果它已經太大,產生一個截止時間定時器,它將執行io_service :: post並繼續讀取我的文件? - 有沒有更好的方法來處理?

+0

好吧。假設你通過async_write發送N個字節。開始你的async_write並同時從文件中讀取下N個字節(2個任務後)。然後當你的async_write完成時,重複同樣的事情。因此,您不會在內存中保留尚未發送的任何文件部分。 –

回答

0

如果要防止dos攻擊,阻塞讀線程並不是一個好主意。你試圖避免的是同時分配太多的資源(內存)。但是打開文件流的數量也是有限的。如果您在超載情況下開始阻止讀取線程,則可以非常快地獲得大量的打開文件流。如果您發現錯誤,您的程序可能不會崩潰,但由於您無法打開其他文件(例如,日誌文件),因此這種行爲肯定是不受歡迎的。

爲了防止這個問題,你必須關心這兩個資源。有很多算法來限制分配資源的數量。對於內存,您可以使用環形緩衝區來讀取數據塊。您還可以使用原子計數器來跟蹤分配的資源數量並建立上限。信號量也可以用來解決這類問題。我寧願最後一個。僞碼看起來像這樣。

Semaphore filestreams(maxNumberOfFilestreams); 
Semaphore memory(maxNumberOfAllocatedChunks); 

// Worker thread to read 
void run() { 
    filestream.wait(); 
    while(!eof) { 
     memory.wait(); 
     // Allocate and read 
    } 
    file.close(); 
    filestream.notify() 
} 

// Sending thread() 

void run() { 
    while(true) { 
     // grab chunk, send and free memory 
     memory.notify(); 
    } 
} 

請記住,open TCP連接也是有限的資源。