抄的日誌

用隊列解決高併發 之 記錄日誌

用隊列解決高併發 之 記錄日誌

 

        在高併發量的情況下,有多種平時不會出現的問題會導致用戶等待,下面我們用日誌記錄爲例來說明一種解決方案——隊列。

創建一個工具類: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.靜態構造函數在引用靜態字段之前會被調用。

 

在新開啓的線程裏面是獲取不到當前上下文的

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章