我需要为ASP.NET应用程序安装一个自定义的日志记录系统。除其他外,它必须记录每个请求的一些数据。我想到了两种方法:
方法#1:为每个请求提交每个条目。例如:创建日志条目并在每次请求时将其提交到数据库(使用临时DbContext
)。我担心这个提交会对服务请求的开销造成不利影响。
方法#2:缓冲区条目,定期提交。例如:创建日志条目并在每个请求上添加到并发缓冲区(使用共享锁)。当超过该缓冲区中的限制时,将获取独占锁,缓冲的条目一次性提交到数据库(使用另一个,也是瞬态DbContext
,仅为每次提交创建和销毁)并且缓冲区为清空。我知道这会使“提交”请求变慢,但这是可以接受的。我也知道关闭/重新启动应用程序可能会导致丢失未提交的日志条目,因为在这种情况下AppDomain会发生变化,但这也是可以接受的。
我已经在我的要求中实现了这两种方法,我已经对它们进行了测试,并且我在本地环境中尽可能地使它们变得紧张。我还没有部署,因此我无法在真实条件下测试它们。两者似乎同样有效,但我不能得出这样的结论。
这两种方法中哪一种最好?我担心在几千名用户的高峰时期的表现。是否有任何我不知道的陷阱?
答案 0 :(得分: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的解决方案,但除了数量限制外,还有一个时间限制。如果在特定秒数内未输入任何日志条目,则队列将被转储到数据库。
答案 1 :(得分:1)
使用log4net,并适当设置其缓冲区大小。那么你可以在一天剩下的时间回家喝啤酒...我相信它是Apache许可的,这意味着你可以根据自己的需要自由修改/重新编译它(适合应用中集成的任何定义,而不是第三方“你要记住。”
严重的是 - 以复杂性为代价优化每个请求的单个数据库插入似乎为时尚早。如果你对每个请求进行10次以上的日志调用,那么缓冲每个请求可能是有意义的 - 但这比编写高性能多线程代码要简单得多且不易出错。
当然,和往常一样,真正的证明就是剖析 - 所以启动一些测试,然后得到一些数字。至少,对您的缓冲记录器执行一批直接插入,并确定每个请求可能存在的差异,以便您做出合理的决定。
直观地说,我不认为它的复杂程度是值得的 - 但我之前的表现一直不错。