2013-05-31 25 views
2

我需要爲ASP.NET應用程序放置一個定製的排序日誌系統。除其他外,它必須爲每個請求記錄一些數據。我想過兩種方法:在ASP.NET應用程序中,我應該緩衝每個請求的日誌條目並不經常提交嗎?

方法1:爲每個請求提交每個條目。例如:在每個請求中創建一個日誌條目並將其提交給數據庫(使用瞬態文件DbContext)。我擔心這種提交會導致服務請求的開銷不夠好。

方法#2:緩衝區條目,定期提交。例如:創建日誌條目並將其添加到每個請求的併發緩衝區(使用共享鎖)。當超過該緩衝區的限制時,會獲得獨佔鎖定,緩衝的條目一次性提交到數據庫(使用另一個,也是臨時的DbContext,僅爲每次提交創建和銷燬),並清空緩衝區。我知道這會使「提交」請求變慢,但這是可以接受的。我也知道,關閉/重新啓動應用程序可能會導致未提交的日誌條目丟失,因爲在這種情況下AppDomain將會更改,但這也是可以接受的。

我已經在我的要求中實施了兩種方法,我測試了它們,並儘可能地在本地環境中盡力處理它們。我還沒有部署,因此我無法在真實條件下測試它們。兩者似乎都工作得很好,但我不能得出這樣的結論。

這兩種方法哪一種最好?我很擔心在幾千用戶的峯值期間的性能。有沒有我不知道的陷阱?

+3

可能取決於您的日誌記錄的詳細和頻繁程度。 –

+0

好吧,幾千個用戶無需擔心。您正在討論使用DbContext並擔心批量插入性能。不會在一起......也許你應該重新考慮使用文件來做日誌記錄並事後將文件導入數據庫 – Pleun

+0

@GeorgeJohnston只要冗長,每個條目不超過100個字節。我想知道,至少考慮採取第二種方法是否過分。 –

回答

1

使用log4net,並適當地設置其緩衝區大小。然後你可以回家並在今天剩下的時間喝杯啤酒......我相信它是Apache許可的,這意味着你可以根據自己的需要自由地修改/重新編譯它(適用於任何「集成在應用程序中的定義」,而不是第三方「你有想法)。儘管如此,認爲每個請求優化一個DB插入代碼似乎爲時過早,但代價是很複雜。如果您爲每個請求執行10次以上的日誌調用,那麼緩衝每個請求可能是有意義的 - 但這比編寫高性能多線程代碼要容易得多,而且更容易出錯。

當然,與往常一樣,真正的證據是在分析 - 所以啓動一些測試,並獲得一些數字。至少,請對您的緩衝記錄器進行一批直插,並確定每次請求可能出現的差異,以便您做出合理的決定。

直覺上來說,我認爲這不值得複雜 - 但我以前在表現上一直是錯誤的。

+0

經過一系列測試後,我發現方法#2始終可以提供從10%到35%的加速,具體取決於緩衝區大小和其他參數。我的實現的複雜性相對較低(否則我根本就不會考慮它),所以我覺得這樣的收益是值得的。我會接受這個答案,建議測試和測量是在這種情況下做出有意義決定的最佳方式。 –

2

爲了解決您對選項1關於放慢每個請求的擔憂,爲什麼不使用TPL將日誌記錄卸載到其他線程?例如:

public class Logger 
{ 

    public static void Log(string message) 
    { 
     Task.Factory.StartNew(() => { SaveMessageToDB(message); }); 
    } 

    private static void SaveMessageToDB(string message) 
    { 
     // etc. 
    } 

} 

HTTP請求線程在寫入條目時不必等待。你也可以調整選項2來做同樣的事情來在不同的線程中寫入累積的消息集。

我實現了一個類似於選項2的解決方案,但除了數字限制外,還有一個時間限制。如果在特定的秒數內沒有輸入日誌條目,則隊列將被轉儲到數據庫。

+0

TPL是我的第一個想法之一,但我不知道ASP.NET應用程序中的線程池如何行爲,我害怕任何隱藏的「陷阱」。 –

相關問題