2012-03-24 37 views
1

我正在開發一個使用ASP.NET MVC3的Web服務。 HTTP API的其中一種方法是從POST請求的主體接收圖像,並需要將其存儲在磁盤上以供進一步處理。 方法的開頭是這樣的:對併發請求的ASP.NET(或IIS?)行爲

Stopwatch stopwatch = new Stopwatch(); 
stopwatch.Start(); 

Interlocked.Increment(ref _generateCount); 

byte[] fileBuffer; 
using (Stream inputStream = Request.InputStream) 
{ 
    if (inputStream.Length == 0) 
    { 
     Trace.WriteLine("Submitted file is empty", "Warning"); 
     inputStream.Close(); 
     Interlocked.Decrement(ref _generateCount); 
     return new HttpStatusCodeResult(400, "Content is empty"); 
    } 

    fileBuffer = new byte[inputStream.Length]; 
    inputStream.Read(fileBuffer, 0, (int)inputStream.Length); 
    inputStream.Close(); 
} 
stopwatch.Stop() 
... (storing the fileBuffer on disk & quite CPU intensive processing on the file) 

我主持的一個小Azure的實例的服務。

現在我的奇怪行爲是當我發出並行請求的服務。 假設我發出第一個請求,並在5秒後發出第二個請求。正如你所看到的,我正在使用秒錶來監視性能。對於第一個請求,ElapsedTime將會非常小(小於一秒),但對於第二個請求,通常讀取大約。 14秒!

請注意,單個請求的平均處理時間約爲。 25秒(並且在處理多個請求時達到40+),所以我在14秒後讀取輸入流,儘管第一個請求還沒有完成。

我該如何解釋這種延遲?

感謝

回答

1

如果你的最終目標是將文件存儲在磁盤你爲什麼在內存加載它嗎?你可以直接寫入到輸出流:

public ActionResult SomeAction() 
{ 
    var stopwatch = Stopwatch.StartNew(); 
    if (Request.InputStream.Length == 0) 
    { 
     return new HttpStatusCodeResult(400, "Content is empty"); 
    } 

    var filename = Server.MapPath("~/app_data/foo.dat"); 
    using (var output = System.IO.File.Create(filename)) 
    { 
     Request.InputStream.CopyTo(output); 
    } 
    stopwatch.Stop(); 

    ... 
} 

另請注意,如果您發出試圖寫入服務器上的同一個文件2個併發請求,則可能會損壞數據,或者因爲你不能寫錯誤同一個文件。

+0

嗨, 我正在加載內存中的流爲調試目的,但直接在磁盤上刷新流似乎確實解決了這個問題。你會如何解釋這種差異?或者它可能來自我的inputStream.Close(),它會等待來自IIS的同步? – ThomasWeiss 2012-03-26 08:09:06

+0

如果我使用log4net日誌記錄進行調試,並將日誌語句寫入特定文件。那麼,併發http請求會覆蓋該日誌文件嗎? – teenup 2013-08-29 08:48:25

+0

@teenup,沒有文件沒有被覆蓋,消息被追加到它。 – 2013-08-29 14:42:56