用队列解决高并发 之 记录日志
在高并发量的情况下,有多种平时不会出现的问题会导致用户等待,下面我们用日志记录为例来说明一种解决方案——队列。
创建一个工具类:LogCommon 如下:
namespace Heima8Web.Common
{
public class LogCommon
{
public static Queue<string> LogQueue = new Queue<string>(); //实例化一个队列
static LogCommon() //日志写入文件的方法在类的静态构造函数中实现,这样,在队列被调用的时候,会自动调用此方法
{
string strFileName = HttpContext.Current.Request.MapPath("/App_Data/Log/" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt"); //在新开启的线程以外获取文件路径(每一个请求对应一个线程,到新的线程里去以后,就不能获得到当前上下文了)
//开启线程池来写日志
ThreadPool.QueueUserWorkItem(a =>
{
while (true)
{
string ex = string.Empty;
lock ("Itcast-DotNet-AspNet-Glable-LogLock")
{
if (LogQueue.Count > 0) //如果队列中有数据,将其出队列
{
ex = LogQueue.Dequeue();
}
else
{
Thread.Sleep(30); //如果没有数据,让线程睡30毫秒,之后进入下一轮循环
continue;
}
}
//创建流,将日志写入到文件中
using (FileStream fs = new FileStream(strFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (StreamWriter writer = new StreamWriter(fs,Encoding.Default))
{
writer.Write(ex.ToString());
}
}
}
});
}
public static void WriteLog(string str) //将日志写入到队列中的方法
{
lock ("Itcast-DotNet-AspNet-Glable-LogLock")
{
LogQueue.Enqueue(str);
}
}
}
}
------------
在 HttpApplication 管道的 Application_Error中注册事件,
即在 global 文件的 Application_Error事件中写如下代码:
protected void Application_Error(Object sender, EventArgs e)
{
Exception ex = Server.GetLastError(); //拿到错误消息
Common.LogCommon.WriteLog(ex.ToString()); //将错误消息加到队列里面去
}
=========================================================
注:在调用 Common.LogCommon.WriteLog 方法的时候,静态构造函数LogCommon()会被自动调用,因为
C#在使用静态构造函数时的几个原则:
1.静态构造函数在创建类的实例之前会被调用,因此在所有实例构造函数之前会被调用。
2.静态构造函数在创建类的第一个实例之前会被调用。
3.静态构造函数在引用静态字段之前会被调用。
在新开启的线程里面是获取不到当前上下文的