介绍

大家都知道性能是API的流行语。而相应时间则是API性能的一个重要并且可测量的参数。在本文中,我们将了解如何使用代码来测量API的响应时间,然后将响应时间数据返回到客户端。

作者:依乐祝

原文地址:https://www.cnblogs.com/yilezhu/p/9520808.html

我们为什么需要测量响应时间

首先,让我们先花一点时间思考下为什么我们需要这么一个特性来测量API的响应时间。下面是编写代码来捕获响应时间的一些场景。

  1. 您需要为您的客户定义API的SLA(服务水平协议)。客户需要了解API响应的时间。响应时间数据可以帮助我们确定API的SLA。
  2. 管理层对报告应用程序的速度快慢感兴趣。您需要有数据来证实您的报告的声明。报告应用程序的性能并与利益相关者进行分享时值得的。
  3. 客户端需要具有API的响应时间的信息,以便它们可以跟踪在客户端和服务器上花费了多少时间。

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

在哪里添加测量代码?

让我们探索一些方法来捕获API的响应时间,主要集中在捕获API中花费的时间。我们的目标是计算从Asp.net Core运行时接收请求到处理响应并从服务器返回结果所经过的时间(以毫秒为单位)。

我们需要忽略哪些因素?

重要的是要理解这个讨论不包括花在N/W上的时间,以及在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;
}

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

  1. 如果API有很多操作,那么我们需要将这个代码添加到多个不利于可维护性的地方。
  2. 此代码仅测量在方法中花费的时间,它不测量在中间件,过滤器,控制器选择,Action选择,模型绑定等其他活动上花费的时间。

第二次尝试

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

我们将实现一个用于计算响应时间的过滤器,如下所示。我们将创建一个Filter并使用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选择Action后执行。因此,它实际上无法检测在其他Asp.net管道中花费的时间。

第三次尝试

我们将使用Asp.net Core中间件来计算API的响应时间

所以,什么是中间件呢?

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

  1. 选择是否将请求传递给管道中的下一个组件。

  2. 可以在调用管道中的下一个组件之前和之后执行工作。

如果您在ASP.NET中使用过HTTPModules或HTTPHandler,那么您可以将中间件视为ASP.NET Core中的替代品。一些中间件的例子是 :

  • MVC中间件

  • Authentication中间件

  • Static File Serving

  • Caching

  • CORS 等等

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

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

    如何处理响应时间数据呢?

    一旦我们捕获到响应时间数据,我们就可以通过以下方式来进行数据的处理。

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

      可能还有其他有用的方法来使用响应时间数据。您可以在评论区进行留言,并告诉我您是如何处理应用程序中的响应时间数据的。

    我们开始写代码吧

    我们将按照下面的处理步骤来进行代码的编写。

    1. 计算API的响应时间数据
    2. 通过在响应头中传递数据将数据报告回客户端应用程序。

    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方法中,一旦请求进入到第一个中间件,我们使用秒表类来启动秒表,然后在处理请求完成后并且响应准备好返回给客户端的Response后停止秒表。OnStarting方法提供了编写自定义代码的机会,以便在将响应头发送到客户端之前添加要调用的委托中。

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

总结

在本文中,我们了解了如何利用ASP.NET中间件来管理跨领域问题,例如测量API的响应时间。使用中间件还有其他各种有用的用例,可以帮助重用代码并提高应用程序的可维护性。

本文翻译自https://www.c-sharpcorner.com/technologies/Asp-Net-core

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=36oxtdlslwowo

如何测量并报告ASP.NET Core Web API请求的响应时间的更多相关文章

  1. [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了

    [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 本文首发自:博客园 文章地址: https://www.cnblogs.com/yilezhu/p/ ...

  2. C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志

    C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...

  3. 使用 Swagger 自动生成 ASP.NET Core Web API 的文档、在线帮助测试文档(ASP.NET Core Web API 自动生成文档)

    对于开发人员来说,构建一个消费应用程序时去了解各种各样的 API 是一个巨大的挑战.在你的 Web API 项目中使用 Swagger 的 .NET Core 封装 Swashbuckle 可以帮助你 ...

  4. 在ASP.NET Core Web API上使用Swagger提供API文档

    我在开发自己的博客系统(http://daxnet.me)时,给自己的RESTful服务增加了基于Swagger的API文档功能.当设置IISExpress的默认启动路由到Swagger的API文档页 ...

  5. Docker容器环境下ASP.NET Core Web API应用程序的调试

    本文主要介绍通过Visual Studio 2015 Tools for Docker – Preview插件,在Docker容器环境下,对ASP.NET Core Web API应用程序进行调试.在 ...

  6. 在docker中运行ASP.NET Core Web API应用程序

    本文是一篇指导快速演练的文章,将介绍在docker中运行一个ASP.NET Core Web API应用程序的基本步骤,在介绍的过程中,也会对docker的使用进行一些简单的描述.对于.NET Cor ...

  7. ASP.NET Core Web API Cassandra CRUD 操作

    在本文中,我们将创建一个简单的 Web API 来实现对一个 “todo” 列表的 CRUD 操作,使用 Apache Cassandra 来存储数据,在这里不会创建 UI ,Web API 的测试将 ...

  8. 在Mac下创建ASP.NET Core Web API

    在Mac下创建ASP.NET Core Web API 这系列文章是参考了.NET Core文档和源码,可能有人要问,直接看官方的英文文档不就可以了吗,为什么还要写这些文章呢? 原因如下: 官方文档涉 ...

  9. ASP.NET Core Web API 开发-RESTful API实现

    ASP.NET Core Web API 开发-RESTful API实现 REST 介绍: 符合REST设计风格的Web API称为RESTful API. 具象状态传输(英文:Representa ...

随机推荐

  1. JS生成URL二维码

    需求:项目中需要在UI界面有一个二维码,扫码后可以跳转到二维码包含的URL. 解决方案:在前端用js生成一个包含URL等信息的二维码. 实现: 方案一. <!DOCTYPE HTML PUBLI ...

  2. 纯css实现无限嵌套菜单

    效果图: demo:关键的地方都以颜色明显标识 <!DOCTYPE html> <html> <head> <title>menu</title& ...

  3. bower简明入门教程

    什么是bower: Bower是一个客户端技术的软件包管理器,它可用于搜索.安装和卸载如JavaScript.HTML.CSS之类的网络资源.其他一些建立在Bower基础之上的开发工具,如YeoMan ...

  4. Mysql双主互备+keeplived高可用架构(部分)

    一.Mysql双主互备+keeplived高可用架构介绍 Mysql主从复制架构可以在很大程度保证Mysql的高可用,在一主多从的架构中还可以利用读写分离将读操作分配到从库中,减轻主库压力.但是在这种 ...

  5. Game Theory

    HDU 5795 || 3032 把x个石子的堆分成非空两(i, j)或三堆(i, j, k)的操作->(sg[i] ^ sg[j])或(sg[i] ^ sg[j] ^ sg[k])是x的后继 ...

  6. MySQL中 指定字段排序函数field()的用法

    MySQL中的field()函数,可以用来对SQL中查询结果集进行指定顺序排序. 函数使用格式如下: order by (str,str1,str2,str3,str4……),str与str1,str ...

  7. lsf运行lsload命令显示“lsload: Host does not have a software license”

    因为这个问题也是花费好长时间了,对一个小白的我来说真的挺激动的.下面说一下我的解决思路吧.不过造成这个问题也有很多种原因,需要对症下药. 我入手解决是从这个网站上看到同样的问题,然后通过一个个排除最后 ...

  8. Spring流行的十大理由

    Spring大概是每个JAVA程序员都听过的框架,但是它为什么能这么流行? 听到咕泡学院的Tom老师的公开课,下面是他总结的阿里为什么选择Spring的十大理由,我觉得这也是Spring能流行的原因: ...

  9. Python开发——16.HTML

    一.HTML 1.服务端 import socket def main(): sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) sock. ...

  10. Python基础-数据类型-转摘

    1.数字 2 是一个整数的例子.长整数 不过是大一些的整数.3.23和52.3E-4是浮点数的例子.E标记表示10的幂.在这里,52.3E-4表示52.3 * 10-4.(-5+4j)和(2.3-4. ...