爱上MVC3系列~监视Action的运行时间,并提供超时记录机制

简介:

文章出现的原因

很久没写关于MVC的文章了,原因是将关注点移向了MVVM和DDD这边,而这篇文章完全是因为公司项目的需要,因为公司网站总是不定时的502,而这由可能是程序超时所引起的,为了分析出现问题的点,所以,对action进行了监控,这个监控功能我选择了在global里注入全局的filter来实现这个功能,为了避免并发,所选择了将记录存储到cache的队列里,再通过quartZ的任务调度功能,来实现数据的IO写入或者数据库与入.

系统流程图

用代码说话

1 建立一个Filter

   /// <summary>
    /// Action渲染页面所需要的时间
    /// </summary>
    public class ActionRenderTimeAttribute : System.Web.Mvc.ActionFilterAttribute
    {
      

        /// <summary>
        /// 锁对象
        /// </summary>
        static object lockObj = new object();
        /// <summary>
        /// 记录进行Action的时间
        /// </summary>
        DateTime joinTime;
        /// <summary>
        /// 进行action之前
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnActionExecuting(System.Web.Mvc.ActionExecutingContext filterContext)
        {
            joinTime = DateTime.Now;
            base.OnActionExecuting(filterContext);
        }
        /// <summary>
        /// 渲染页面HTML之后
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnResultExecuted(System.Web.Mvc.ResultExecutedContext filterContext)
        {
            int outSeconds;//! 超时的秒数,默认为60S
            int.TryParse((System.Configuration.ConfigurationManager.AppSettings["ActionRenderTime"] ?? "60").ToString(), out outSeconds);
            var timeSpan = (DateTime.Now - joinTime).Seconds;
            if (timeSpan > outSeconds)
            {
                lock (lockObj)
                {
                    var temp = (System.Web.HttpRuntime.Cache["RunTime"] as Queue<Tuple<int, string>>) ?? new Queue<Tuple<int, string>>();
                    temp.Enqueue(new Tuple<int, string>(timeSpan, filterContext.RequestContext.HttpContext.Request.Url.AbsoluteUri));
                    System.Web.HttpRuntime.Cache.Insert("RunTime", temp);
                }
            }

            base.OnResultExecuted(filterContext);
        }


    }

2 为filter加全局注入点

 public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new MVVM.ActionRenderTimeAttribute());
        }
    }

3 建立一个QuartZ的任务

   /// <summary>
    /// 工作任务基类
    /// </summary>
    public abstract class JobBase
    {
        /// <summary>
        /// log4日志对象
        /// </summary>
        protected log4net.ILog Logger
        {
            get
            {
                return log4net.LogManager.GetLogger(this.GetType());//得到当前类类型(当前实实例化的类为具体子类)
            }
        }
    }
    public class ActionTimeJob : JobBase, IJob
    {

        #region Fields & Properties
        /// <summary>
        /// 锁对象
        /// </summary>
        private static object lockObj = new object();
        #endregion

        #region IJob 成员

        public void Execute(IJobExecutionContext context)
        {
            lock (lockObj)
            {
                try
                {
                    if ((System.Web.HttpRuntime.Cache["RunTime"] as Queue<Tuple<int, string>>) != null
                        && (System.Web.HttpRuntime.Cache["RunTime"] as Queue<Tuple<int, string>>).Count > 0)
                    {
                        var temp = (System.Web.HttpRuntime.Cache["RunTime"] as Queue<Tuple<int, string>>).Dequeue();
                        if (temp != null)
                        {
                            //! 超时,开始记录日志
                            global::Logger.Core.LoggerFactory.Instance.Logger_Info(
                                        string.Format("出现异常的页面:{0},页面加载需要的时间:{1}秒,异常发生时间:{2}"
                                        , temp.Item2, temp.Item1, DateTime.Now),"actionTime.log");
                        }
                    }
                }
                catch (Exception ex )
                {

                    throw ex;
                }
            }
        }

        #endregion
    }

4 在global里配置QuartZ注入点

#region quartZ调度中心
            const string DEFAULTINTERVAL = "300";//默认为5分钟
            string user_Classroom_RJobInterval = ConfigurationManager.AppSettings["ActionRunTimeJob"]
          ?? DEFAULTINTERVAL;

            ISchedulerFactory sf = new Quartz.Impl.StdSchedulerFactory();
            IScheduler sched = sf.GetScheduler();
            //一个工作可以由多个组组成,而每个组又可以由多个trigger组成
            IDictionary<IJobDetail, IList<ITrigger>> scheduleJobs = new Dictionary<IJobDetail, IList<ITrigger>>();

            #region ActionRunTimeJob
            scheduleJobs.Add(JobBuilder.Create<ActionTimeJob>()
               .WithIdentity("job1", "group1")
               .Build(),
               new List<ITrigger> 
                    { 
                     (ICronTrigger)TriggerBuilder.Create()
                                                 .WithIdentity("trigger", "group1")
                                                 .WithCronSchedule(user_Classroom_RJobInterval)
                                                 .Build() 
                    });

            sched.ScheduleJobs(scheduleJobs, true);
            sched.Start();
            #endregion
            #endregion

5 在config里配置相关调度和性能监控的信息

    <!-- 每次得到的数据行数,以便减少内存的占用-->
    <add key="DataRow" value="1"/>
    <!-- 每3秒执行一次-->
    <add key="ActionRunTimeJob" value="0/3 * * * * ?"/>
    <!-- 每页面渲染时间超时为1秒-->
    <add key="ActionRenderTime" value="1"/>
    <!-- 是否开启action性能监控-->
    <add key="isActionRender" value="1"/>

6 程序效果截图

本文转自博客园张占岭(仓储大叔)的博客,原文链接:爱上MVC3系列~监视Action的运行时间,并提供超时记录机制,如需转载请自行联系原博主。

目录
相关文章
|
3月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
47 0
|
6月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
189 0
|
6月前
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
78 0
|
存储 开发框架 前端开发
[回馈]ASP.NET Core MVC开发实战之商城系统(五)
经过一段时间的准备,新的一期【ASP.NET Core MVC开发实战之商城系统】已经开始,在之前的文章中,讲解了商城系统的整体功能设计,页面布局设计,环境搭建,系统配置,及首页【商品类型,banner条,友情链接,降价促销,新品爆款】,商品列表页面,商品详情等功能的开发,今天继续讲解购物车功能开发,仅供学习分享使用,如有不足之处,还请指正。
163 0
|
开发框架 前端开发 .NET
[回馈]ASP.NET Core MVC开发实战之商城系统(三)
[回馈]ASP.NET Core MVC开发实战之商城系统(三)
99 0
|
开发框架 前端开发 .NET
[回馈]ASP.NET Core MVC开发实战之商城系统(一)
[回馈]ASP.NET Core MVC开发实战之商城系统(一)
173 0
|
SQL 开发框架 前端开发
[回馈]ASP.NET Core MVC开发实战之商城系统(开篇)
[回馈]ASP.NET Core MVC开发实战之商城系统(开篇)
212 0
|
开发框架 缓存 JSON
ASP.NET Core MVC 从入门到精通之Filter
ASP.NET Core MVC 从入门到精通之Filter
176 0
|
开发框架 自然语言处理 前端开发
基于ASP.NET MVC开发的、开源的个人博客系统
基于ASP.NET MVC开发的、开源的个人博客系统
83 0