·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设开发 >> ASP.NET网站开发 >> 使用Metrics.NET 构建 ASP.NET MVC 应用程序的性能指标

使用Metrics.NET 构建 ASP.NET MVC 应用程序的性能指标

作者:佚名      ASP.NET网站开发编辑:admin      更新时间:2022-07-23

使用Metrics.NET 构建 asp.net MVC 应用程序的性能指标

通常我们需要监测ASP.NET MVC 或 Web API 的应用程序的性能时,通常采用的是自定义性能计数器,性能计数器会引发无休止的运维问题(损坏的计数器、权限问题等)。这篇文章向你介绍一个新的替代性能计数器的工具Metrics.NET,因为是它是内部的,所以我们能够向系统中添加更多更有意义的度量标准。

Metrics.NET(https://github.com/etishor/Metrics.NET)是一个给CLR 提供度量工具的包,它是移植自java的metrics,支持的平台 .NET 4.5.1, .NET 4.5, .NET 4.0 和 Mono 3.8.0,在c#代码中嵌入Metrics代码,可以方便的对业务代码的各个指标进行监控, 提供5种度量的类型:Gauges, Counters, Histograms, Meters,Timers:

Gauges

Gauge是最简单的度量类型,只有一个简单的返回值,例如,你的应用中有一个由第三方类库中保持的一个度量值,你可以很容易的通过Gauge来度量他

        long milliseconds = this.ConvertTicksToMilliseconds(elapsedTicks);            String controllerName = this.actionInfo.ControllerName;            String actionName = this.actionInfo.ActionName;            string counterName = string.Format("{0} {1} {2}", controllerName, actionName, COUNTER_NAME);            Metric.Context(this.actionInfo.ActionType).Gauge(counterName, () => milliseconds, Unit.Custom("Milliseconds"));

那么Metrics会创建一个叫做[MVC] Account LogOn Last Call Elapsed Time.Gauge的Gauge,返回最新的一个请求的时间。

Counters

Counter是一个简单64位的计数器:

        String categoryName = this.actionInfo.ControllerName;            String instanceName = this.actionInfo.ActionName;            string counterName = string.Format("{0} {1} {2}", categoryName, instanceName, COUNTER_NAME);            this.callsInPRogressCounter = Metric.Context(this.actionInfo.ActionType).Counter(counterName, Unit.Custom(COUNTER_NAME));              /// <summary>        /// Constant defining the name of this counter        /// </summary>        public const String COUNTER_NAME = "ActiveRequests";        private Counter callsInProgressCounter;        /// <summary>        /// Method called by the custom action filter just prior to the action begining to execute        /// </summary>        /// <remarks>        /// This method increments the Calls in Progress counter by 1        /// </remarks>        public override void OnActionStart()        {            this.callsInProgressCounter.Increment();        }        /// <summary>        /// Method called by the custom action filter after the action completes        /// </summary>        /// <remarks>        /// This method decrements the Calls in Progress counter by 1        /// </remarks>        public override void OnActionComplete(long elapsedTicks, bool exceptionThrown)        {            this.callsInProgressCounter.Decrement();        }所有的Counter都是从0开始,上述代码描述的当前的请求数。

Histograms-直方图

Histrogram是用来度量流数据中Value的分布情况,例如,每一个POST/PUT请求中的内容大小:

        public PostAndPutRequestSizeMetric(ActionInfo info)            : base(info)        {            this.histogram = Metric.Context(this.actionInfo.ActionType).Histogram(COUNTER_NAME, Unit.Bytes, SamplingType.FavourRecent);        }        /// <summary>        /// Constant defining the name of this counter        /// </summary>        public const String COUNTER_NAME = "Post & Put Request Size";        /// <summary>        /// Reference to the performance counter         /// </summary>        private Histogram histogram;        public override void OnActionStart()        {            var method = this.actionInfo.HttpMethod.ToUpper();            if (method == "POST" || method == "PUT")            {                histogram.Update(this.actionInfo.ContentLength);            }        }

Histrogram 的度量值不仅仅是计算最大/小值、平均值,方差,他还展现了分位数(如中位数,或者95th分位数),如75%,90%,98%,99%的数据在哪个范围内。

传统上,中位数(或者其他分位数)是在一个完整的数据集中进行计算的,通过对数据的排序,然后取出中间值(或者离结束1%的那个数字,来计算99th分位数)。这种做法是在小数据集,或者是批量计算的系统中,但是在一个高吞吐、低延时的系统中是不合适的。

一个解决方案就是从数据中进行抽样,保存一个少量、易管理的数据集,并且能够反应总体数据流的统计信息。使我们能够简单快速的计算给定分位数的近似值。这种技术称作reservoir sampling。

Metrics中提供两种类型的直方图:uniform跟biased。

Uniform Histograms

Uniform Histogram提供直方图完整的生命周期内的有效的中位数,它会返回一个中位值。例如:这个中位数是对所有值的直方图进行了更新,它使用了一种叫做Vitter’s R的算法,随机选择了一些线性递增的样本。

当你需要长期的测量,请使用Uniform Histograms。在你想要知道流数据的分布中是否最近变化的话,那么不要使用这种。

Biased Histograms

Biased Histogram提供代表最近5分钟数据的分位数,他使用了一种forward-decayingpriority sample的算法,这个算法通过对最新的数据进行指数加权,不同于Uniform算法,Biased Histogram体现的是最新的数据,可以让你快速的指导最新的数据分布发生了什么变化。Timers中使用了Biased Histogram。

Meters

Meter度量一系列事件发生的比率:

 public DeltaExceptionsThrownMetric(ActionInfo info)            : base(info)        {            this.deltaExceptionsThrownCounter                = Metric.Context(this.actionInfo.ActionType).Meter(COUNTER_NAME, Unit.Errors, TimeUnit.Seconds);        }        /// <summary>        /// Constant defining the name of this counter        /// </summary>        public const String COUNTER_NAME = "Errors";        /// <summary>        /// Reference to the performance counter         /// </summary>        private Meter deltaExceptionsThrownCounter;        /// <summary>        /// Method called by the custom action filter after the action completes        /// </summary>        /// <remarks>        /// If exceptionThrown is true, then the Total Exceptions Thrown counter will be         /// incremented by 1        /// </remarks>        public override void OnActionComplete(long elapsedTicks, bool exceptionThrown)        {            if (exceptionThrown)                this.deltaExceptionsThrownCounter.Mark();        }

Meter需要除了Name之外的两个额外的信息,事件类型(enent type)跟比率单位(rate unit)。事件类型简单的描述Meter需要度量的事件类型,在上面的例子中,Meter是度量失败的请求数,所以他的事件类型也叫做“Errors”。比率单位是命名这个比率的单位时间,在上面的例子中,这个Meter是度量每秒钟的失败请求次数,所以他的单位就是秒。这两个参数加起来就是表述这个Meter,描述每秒钟的失败请求数。

Meter从几个角度上度量事件的比率,平均值是时间的平均比率,它描述的是整个应用完整的生命周期的情况(例如,所有的处理的请求数除以运行的秒数),它并不描述最新的数据。幸好,Meters中还有其他3个不同的指数方式表现的平均值,1分钟,5分钟,15分钟内的滑动平均值。

Hint:这个平均值跟Unix中的uptime跟top中秒数的Load的含义是一致的。

Timers

Timer是Histogram跟Meter的一个组合

 public TimerForEachRequestMetric(ActionInfo info)            : base(info)        {            String controllerName = this.actionInfo.ControllerName;            String actionName = this.actionInfo.ActionName;            string counterName = string.Format("{0}{1}", controllerName, actionName);            this.averageTimeCounter = Metric.Context(this.actionInfo.ActionType).Timer(counterName, Unit.Requests, SamplingType.FavourRecent,                TimeUnit.Seconds, TimeUnit.Milliseconds);        }        #region Member Variables        private Timer averageTimeCounter;        #endregion        /// <summary>        /// Method called by the custom action filter after the action completes        /// </summary>        /// <remarks>        /// This method increments the Average Time per Call counter by the number of ticks        /// the action took to complete and the base counter is incremented by 1 (this is        /// done in the PerfCounterUtil.IncrementTimer() method).          /// </remarks>        /// <param name="elapsedTicks">A long of the number of ticks it took to complete the action</param>        public override void OnActionComplete(long elapsedTicks, bool exceptionThrown)        {            averageTimeCounter.Record(elapsedTicks, TimeUnit.Nanoseconds);        }

Timer需要的参数处理Name之外还需要,持续时间单位跟比率时间单位,持续时间单位是要度量的时间的期间的一个单位,在上面的例子中,就是MILLISECONDS,表示这段周期内的数据会按照毫秒来进行度量。比率时间单位跟Meters的一致。

Health Checks(健康检查)

Meters提供一种一致的、统一的方法来对应用进行健康检查,健康检查是一个基础的对应用是否正常运行的自我检查。

Reporters报告

Reporters是将你的应用中所有的度量指标展现出来的一种方式,metrics.net中用了三种方法来导出你的度量指标,Http,Console跟CSV文件, Reporters是可定制的。例如可以使用Log4net进行输出,具体参见 https://github.com/nkot/Metrics.Log4Net 。

  Metric.Config.WithHttpEndpoint("http://localhost:1234/")                .WithAllCounters()                .WithReporting(config => config.WithCSVReports(@"c:\temp\csv", TimeSpan.FromSeconds(10))                    .WithTextFileReport(@"C:\temp\reports\metrics.txt", TimeSpan.FromSeconds(10)));<