• 关于面向切面编程的部分内容-错误处理机制


    错误处理机制。

    面对多个web服务器,多线程处理,我们想把错误信息记录到一个txt文档中。

    但是把错误信息写到内存是很快。写到硬盘上就有一堆的问题。比如说读写慢、并发问题。

    今天我们就利用这个实现错误处理 此文以MVC为例

    1、首先要在  golable  文件的  protected void Application_Start()


    注册一个错误处理机制。

    MVC中自带一个  过滤器

    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

    image

    这里面 我们看到这个过滤器

    2、其实就是在 app_Start文件夹下面 的 FilterConfig.cs 文件

    image

    3、 打开FilterConfig.cs文件

    就写了一个注册事件。我们看得到 这个是对错误处理机制

    image

    (当然 ,你们看到的是  HandleErrorAttribute 这个类)

    4、所以你们可能觉得奇怪,我们来查看MyExceptionAttribut的定义看一下

    image

    继承了HandleErrorAttribute

    这里我把这个类的代码贴一下


    public class MyExceptionAttribute : HandleErrorAttribute
        {
            //  private static object obj = new object();
            public static ConcurrentQueue<Exception> ExceptionQueue = new ConcurrentQueue<Exception>();//定义队列

            /// <summary>
            /// 在该方法中捕获异常。
            /// </summary>
            /// <param name="filterContext"></param>
            public override void OnException(ExceptionContext filterContext)
            {

                base.OnException(filterContext);
                Exception ex = filterContext.Exception;//捕获异常信息。
                //将异常信息写到队列中。
                ExceptionQueue.Enqueue(ex);
                //跳转到错误页面.
                filterContext.HttpContext.Response.Redirect("/Error.html");

              

            }
        }

    主要是定义一个静态 队列  ConcurrentQueue

    (当然你也可以用 Queue。但是微软说 这个ConcurrentQueue 比 Queue  安全。好像是线程安全的,一堆堆的理论,说白了就是用ConcurrentQueue 更安全)

    这样所有的错误就都在这个队列里面了。(就是内存)

    这样总不行吧。内存 断电就没有了的啊。

    所以我们要想把资料存到 硬盘中。

    5、现在又要在

      golable  文件的  protected void Application_Start()


    中注册一个消费线程(这句话后面会解释,看不懂就继续)就是在 protected void Application_Start()中加入这些代码,最好放最前面。

    内容就是线程池开启一个线程 从刚刚定义的 MyExceptionAttribute的 ExceptionQueue队列里面取出项来。

    将错误信息最加到文件后面。如果队列为空,就线程停留3秒。


    string filePath = Server.MapPath("/Log/");
                ThreadPool.QueueUserWorkItem((a) =>
                {

                    while (true)//注意:线程不能结束。后面写到队列中的数据没法处理。
                    {

        // 这里可以加一条   if (MyExceptionAttribute.ExceptionQueue.Count() > 0)
    //{  发送邮件到管理员}
                        if (MyExceptionAttribute.ExceptionQueue.Count() > 0)
                        {
                            // Exception ex= MyExceptionAttribute.ExceptionQueue.Dequeue();//从队列中取出数据.
                            Exception ex = null;
                            bool isResult = MyExceptionAttribute.ExceptionQueue.TryDequeue(out ex);
                            if (ex != null && isResult)
                            {
                                string fullPath = filePath + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
                                File.AppendAllText(fullPath, ex.ToString());
                             //   ILog logger = LogManager.GetLogger("errorMsg");
                              //  logger.Error(ex.ToString());
                            }
                            else
                            {
                                Thread.Sleep(3000);
                            }
                        }
                        else
                        {
                            Thread.Sleep(3000);//避免造成CPU的空转。
                        }
                    }

                }, filePath);

    6、总结。

    这个就是一个生产者消费者的模式。

    生产者就是 产生错误的源头。 消费者就是注册保存日志的方法。

    中间有一个仓库就是    那个静态错误队列。

    可以看到 系统产生的错误临时存放于内存中。然后一个新的线程 去读写静态错误队列。

    正常情况 需要在错误队列里面加一个错误队列数字大于1000条的时候  发警告到邮箱的功能。那样感觉有点问题复杂化了,毕竟这里只是讲错误处理。

    7、log4net 我前面讲过的一个开源框架 记录错误很好。

    这里提供一个连接    log4net配置方法你可以把那个一起并到这里。那么就会有

    把protected void Application_Start()中添加 的代码

    改成。注意是改成:

    log4net.Config.XmlConfigurator.Configure();
                //开始一个线程,查看异常队列
                string filePath = Server.MapPath("/Log/");
                ThreadPool.QueueUserWorkItem((a) =>
                {

                    while (true)//注意:线程不能结束。后面写到队列中的数据没法处理。
                    {
                        if (MyExceptionAttribute.ExceptionQueue.Count() > 0)
                        {
                            // Exception ex= MyExceptionAttribute.ExceptionQueue.Dequeue();//从队列中取出数据.
                            Exception ex = null;
                            bool isResult = MyExceptionAttribute.ExceptionQueue.TryDequeue(out ex);
                            if (ex != null && isResult)
                            {
                                string fullPath = filePath + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
                                //File.AppendAllText(fullPath, ex.ToString());
                                ILog logger = LogManager.GetLogger("errorMsg");
                                logger.Error(ex.ToString());
                            }
                            else
                            {
                                Thread.Sleep(3000);
                            }
                        }
                        else
                        {
                            Thread.Sleep(3000);//避免造成CPU的空转。
                        }
                    }

                }, filePath);

    这样就会按照你的要求把错误日志记录到

    app_data文件夹下面。(前提是你有未处理的错误 。呵呵)

    看到下图就成功了

    image

    题外话(

    没有就自己创一个   var s=3/0;

    这样就可以了。

  • 相关阅读:
    Python之旅.第十章.mysql..
    Python之旅.第十章.mysql.
    Python之旅.第十章.mysql.
    Python之旅.第十章.mysql。
    Mac 移动光标和删除
    网络编程——socket开发
    闭包(closure)
    命名空间 and 作用域
    Function
    for循环的禁忌
  • 原文地址:https://www.cnblogs.com/jixinyu12345/p/4862859.html
Copyright © 2020-2023  润新知