测量和报告ASP.NET Core API的响应时间

903 阅读6分钟

介绍

性能是API的流行语。API性能的最重要且可衡量的参数之一是响应时间。在本文中,我们将了解如何添加代码以测量API的响应时间,然后将响应时间数据返回给最终客户端。

需要些什么?

让我们花点时间思考为什么我们将需要这样的功能来测量API的响应时间。以下是一些要点,它们是编写代码以捕获响应时间的灵感。

您需要为与客户的API定义SLA(服务水平协议)。客户需要了解API花费多少时间来回复。随着时间的过去,响应时间数据可以帮助我们确定API的SLA。

管理层对有关应用程序快慢的报告感兴趣。您需要数据来证实您的主张。值得报告应用程序的性能并与利益相关者共享。

客户端需要具有API响应时间的信息,以便他们可以跟踪在客户端和服务器上花费了多少时间。

您可能在项目中也遇到过类似的请求,因此值得研究一种捕获API响应时间的方法。

在哪里添加代码?

让我们探索几种方法来捕获API的响应时间,主要集中在捕获API内部花费的时间。我们的目标是计算从Asp.net Core接收到请求到服务器处理响应并将其发送回之间所经过的时间(以毫秒为单位)。

我们忽略什么因素?

让我们对讨论的范围作一些说明,此处的讨论不包括花费在网络上的时间和花费在IIS上的时间以及应用程序池启动。如果应用程序池未启动并且正在运行,则第一个请求可能会影响API的总体响应时间。我们可以使用一个应用程序初始化模块解决这个问题,但这超出了本文的范围。

第一次尝试

捕获API响应时间的一种非常容易想到的方法是在开始和结束时向每个API方法添加代码,然后测量增量以计算响应时间,如下所示。

// GET api/values/5   
[HttpGet]  
public IActionResult Get() {  
    // Start the watch   
    var watch = new Stopwatch();  
    watch.Start();  
    // Your actual Business logic   
    // End the watch  
    watch.Stop();  
    var responseTimeForCompleteRequest = watch.ElapsedMilliseconds;  
} 

该代码应该能够计算出操作所花费的时间。但是,由于以下原因,这似乎不是一个良好的方法。

如果一个API有很多操作,那么我们需要将此代码添加到多个位置,这将不利于维护。

此代码仅测量方法花费的时间,不测量在中间件,过滤器,控制器选择,操作方法选择,模型绑定等其他活动上花费的时间。

第二次尝试

让我们尝试通过将代码集中在一个地方来改进上述代码,以便于维护。我们需要在执行方法之前和之后执行响应时间计算代码。如果您使用过早期版本的Asp.net Web API,您将熟悉过滤器的概念。过滤器使您可以在请求处理管道中的特定阶段之前或之后运行代码。

我们将实现一个过滤器,用于计算响应时间,如下所示。我们将创建一个过滤器并使用OnActionExecuting启动计时器,然后在OnActionExecuted方法中停止计时器,从而计算API的响应时间。

    public class ResponseTimeActionFilter: IActionFilter {  
        private const string ResponseTimeKey = "ResponseTimeKey";  
        public void OnActionExecuting(ActionExecutingContext context) {  
            // Start the timer   
            context.HttpContext.Items[ResponseTimeKey] = Stopwatch.StartNew();  
        }  
        public void OnActionExecuted(ActionExecutedContext context) {  
            Stopwatch stopwatch = (Stopwatch) context.HttpContext.Items[ResponseTimeKey];  
            // Calculate the time elapsed   
            var timeElapsed = stopwatch.Elapsed;  
        }  
    }  

该代码仍然不是用于计算响应时间的最可靠技术,因为它没有解决计算执行中间件,控制器选择,操作方法选择,模型绑定等所花费的时间的问题。过滤器管道在MVC选择要执行的动作。因此,它实际上无法衡量花费在Other Asp.net管道中的时间。

第三次尝试

哪么最终我们选择使用Asp.net Core中间件来计算API的响应时间。

那么,什么是中间件?

基本上,中间件是处理请求/响应的软件组件。中间件被组装到应用程序管道中并服务于传入的请求。每个组件执行以下操作。

选择是否将请求传递到管道中的下一个组件。 可以在调用管道中的下一个组件之前和之后执行工作。

如果您在ASP.NET中使用过HTTPModules或HTTPHandlers,则可以将中间件视为ASP.NET Core中的替代品。中间件的一些示例是-

MVC Middleware
Authentication
Static File Serving
Caching
CORS

我们希望添加代码以在请求进入ASP.NET Core管道后启动计时器,并在管道处理响应后停止计时器。在请求管道的开始处使用自定义中间件似乎是最好的方法,它可以尽早获取对请求的访问,并在管道中执行最后一步之前进行访问。

我们将构建一个响应时间中间件,将其作为第一个中间件添加到请求管道中,以便我们可以在请求进入Asp.net核心管道后立即启动计时器。

响应时间数据怎么办?

捕获响应时间数据后,我们可以通过以下方式处理数据。

将响应时间数据添加到报告数据库或分析解决方案。 将响应时间数据写入日志文件。 将响应时间数据传递到消息队列,该消息队列可以由另一个应用程序进一步处理以进行报告和分析。 使用响应头将响应时间信息发送到使用我们的Rest API的客户端应用程序。

使用响应时间数据可能还有其他有用的方法。请发表评论,告诉我您如何处理应用程序中的响应时间数据。

让我们写代码

我们将考虑以下几点来编写代码。

计算API的响应时间数据 通过在Response Header中传递数据,将数据返回客户端应用程序。

下面显示了ResponseTimeMiddleware的完整代码段。

public class ResponseTimeMiddleware {  
    // Name of the Response Header, Custom Headers starts with "X-"  
    private const string RESPONSE_HEADER_RESPONSE_TIME = "X-Response-Time-ms";  
    // Handle to the next Middleware in the pipeline  
    private readonly RequestDelegate _next;  
    public ResponseTimeMiddleware(RequestDelegate next) {  
        _next = next;  
    }  
    public Task InvokeAsync(HttpContext context) {  
        // Start the Timer using Stopwatch  
        var watch = new Stopwatch();  
        watch.Start();  
        context.Response.OnStarting(() => {  
            // Stop the timer information and calculate the time   
            watch.Stop();  
            var responseTimeForCompleteRequest = watch.ElapsedMilliseconds;  
            // Add the Response time information in the Response headers.   
            context.Response.Headers[RESPONSE_HEADER_RESPONSE_TIME] = responseTimeForCompleteRequest.ToString();  
            return Task.CompletedTask;  
        });  
        // Call the next delegate/middleware in the pipeline   
        return this._next(context);  
    }  
} 

代码说明

有趣的部分发生在InvokeAsync方法中,一旦请求进入请求的第一个中间件,我们就使用Stopwatch类来启动秒表,然后在处理完请求并将响应准备好发送回给应用程序后停止秒表。OnStarting方法提供了编写自定义代码的机会,以添加将在响应标头发送到客户端之前要调用的委托。

最后,我们在“自定义标头”中添加“响应时间”信息。我们使用X-Response-Time-ms作为响应标头。按照惯例,自定义标头以X开头。

结论

在本文中,我们了解了如何利用ASP.NET中间件来管理横切关注点,例如测量API的响应时间。使用中间件还有许多其他有用的用例,它们可以帮助重用代码并提高应用程序的可维护性。

原文链接: www.c-sharpcorner.com/article/mea…