1.自定義異常處理過濾器類文件html
新建MyExceptionAttribute.cs異常處理類文件數據庫
MyExceptionAttribute.cs代碼以下:安全
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace WebApp.Models { public class MyExceptionAttribute : HandleErrorAttribute { public static Queue<Exception> exceptionQueue = new Queue<Exception>(); //異常處理隊列對象 /// <summary> /// 控制器方法中出現異常,會調用該方法捕獲異常 /// </summary> /// <param name="filterContext"></param> public override void OnException(ExceptionContext filterContext) { exceptionQueue.Enqueue(filterContext.Exception);//將捕獲的異常信息寫到隊列中 filterContext.HttpContext.Response.Redirect("/Error.html");//跳轉到錯誤頁面 base.OnException(filterContext); } } }
2.將錯誤處理過濾器修改成自定義的異常處理過濾器服務器
修改以下:併發
using System.Web; using System.Web.Mvc; using WebApp.Models; namespace WebApp { public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { //filters.Add(new HandleErrorAttribute()); filters.Add(new MyExceptionAttribute());//使用自定義異常處理的過濾器 } } }
3.修改Global.asax文件,在程序首次加載的時候,開啓線程掃描異常隊列,處理異常信息ide
using Spring.Web.Mvc; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; using WebApp.Models; namespace WebApp { // 注意: 有關啓用 IIS6 或 IIS7 經典模式的說明, // 請訪問 http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : SpringMvcApplication //System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); #region 開啓線程掃描異隊列,處理異常信息 string fileLogPath = Server.MapPath("/Log/");//知道用來保存錯誤日誌文件的文件夾路徑 //開啓一個線程掃描日誌隊列 ThreadPool.QueueUserWorkItem((a) => { while (true) { if (MyExceptionAttribute.exceptionQueue.Count > 0) //判斷隊列中是否有數據 { Exception ex = MyExceptionAttribute.exceptionQueue.Dequeue();//出隊 if (ex != null) { string fileName = DateTime.Now.ToString("yyyy-MM-dd") + ".txt"; File.AppendAllText(fileLogPath + fileName, ex.ToString(), Encoding.Default);//將異常追加寫入到文件中 } else { Thread.Sleep(3000); } } else { Thread.Sleep(3000);//若是隊列中沒有數據,讓當前線程休息3秒鐘,避免形成CPU空轉,避免CPU的浪費 } } }, fileLogPath); #endregion } } }
4.測試:高併發
public ActionResult Index() { int a = 2; int b = 0; int c = a / b; return Content(c.ToString()); }
5.效果性能
6.其餘說明:測試
1.解決高併發錯誤日誌問題:
1.1用傳統lock方式,若是併發量很大的話,用戶會出現卡頓的狀況。
1.2.在服務器開闢一個隊列,存儲用戶錯誤信息,而後單獨開啓一個線程來處理,就不會有卡頓狀況。(隊列是在內存中,寫入速度很快)
這就是生產者消費者模式
2.Global下Application_Start()方法只在程序首次執行時調用
3.ThreadPool線程池線程性能很好,比咱們本身建立線程的效率要高不少。
4.池用來解決對象頻繁建立的問題,頻繁建立消耗性能。
5.Queue自己不是線程安全的,作下面的處理後就能夠保證是線程內安全的了,就不會出現併發問題。spa
Queue queue = Queue.Synchronized(myQueue);
7.源碼下載: