用队列解决高并发 之 记录日志

用队列解决高并发 之 记录日志

 

        在高并发量的情况下,有多种平时不会出现的问题会导致用户等待,下面我们用日志记录为例来说明一种解决方案——队列。

创建一个工具类: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.静态构造函数在引用静态字段之前会被调用。

在新开启的线程里面是获取不到当前上下文的

原文地址:https://www.cnblogs.com/key1309/p/3402859.html