如何测量并报告ASP.NET Core Web API请求的响应时间
如何测量并报告ASP.NET Core Web API请求的响应时间
介绍
大家都知道性能是API的流行语。而相应时间则是API性能的一个重要并且可测量的参数。在本文中,我们将了解如何使用代码来测量API的响应时间,然后将响应时间数据返回到客户端。
我们为什么需要测量响应时间
首先,让我们先花一点时间思考下为什么我们需要这么一个特性来测量API的响应时间。下面是编写代码来捕获响应时间的一些场景。
- 您需要为您的客户定义API的SLA(服务水平协议)。客户需要了解API响应的时间。响应时间数据可以帮助我们确定API的SLA。
- 管理层对报告应用程序的速度快慢感兴趣。您需要有数据来证实您的报告的声明。报告应用程序的性能并与利益相关者进行分享时值得的。
- 客户端需要具有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; }
此代码应该能够计算操作所花费的时间。但由于以下原因,这似乎不是正确的方法。
- 如果API有很多操作,那么我们需要将这个代码添加到多个不利于可维护性的地方。
- 此代码仅测量在方法中花费的时间,它不测量在中间件,过滤器,控制器选择,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的响应时间
所以,什么是中间件呢?
基本上,中间件是处理请求/响应的软件组件。中间件被组装到应用程序管道中并在传入请求中提供服务。每个组件执行以下操作。
- 选择是否将请求传递给管道中的下一个组件。
- 可以在调用管道中的下一个组件之前和之后执行工作。
如果您在ASP.NET中使用过HTTPModules或HTTPHandler,那么您可以将中间件视为ASP.NET Core中的替代品。一些中间件的例子是 :
- MVC中间件
- Authentication中间件
- Static File Serving
- Caching
- CORS 等等
我们希望在请求进入ASP.NET Core管道后添加代码以启动计时器,并在管道处理响应后停止计时器。请求管道开始时的自定义中间件似乎是访问请求最早访问并在管道中执行最后一步之前进行访问的最佳方法。
我们将构建一个响应时间中间件,我们将其作为第一个中间件添加到请求管道中,以便我们可以在请求进入Asp.net Core管道后立即启动计时器。
### 如何处理响应时间数据呢?
一旦我们捕获到响应时间数据,我们就可以通过以下方式来进行数据的处理。
- 将响应时间数据添加到报告数据库或分析解决方案。
- 将响应时间数据写入日志文件。
- 将响应时间数据传递到消息队列,该消息队列可以由另一个应用程序进一步处理以进行报告和分析。
- 使用响应头将响应时间信息发送到使用我们的Rest API的客户端应用程序。
可能还有其他有用的方法来使用响应时间数据。您可以在评论区进行留言,并告诉我您是如何处理应用程序中的响应时间数据的。
### 我们开始写代码吧
我们将按照下面的处理步骤来进行代码的编写。
- 计算API的响应时间数据
- 通过在响应头中传递数据将数据报告回客户端应用程序。
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的响应时间。使用中间件还有其他各种有用的用例,可以帮助重用代码并提高应用程序的可维护性。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
车联网上云最佳实践(一)
一、车联网行业特性讲解 最近两年车联网发展受到政府部门、科研院以及各大互联网巨头的广泛关注和积极推动。从应用来看,主要包括两种模式:一是前装模式(即车辆出厂前安装),是乘用车厂主导或者与有相关能力的公司合作,例如上汽和阿里巴巴的合作。另一种就是后装模式(通常是将车机设备安装在汽车的OBD接口上例如各类汽车盒子等等。原理是利用智能终端(即车机)采集汽车OBD接口CAN总线上的所有原始数据进行诊断,数据分析,记录行车信息,并将数据解析出其具体意义(汽车内部电控系统的各项传感器数值)后通过串口输出,供用户读取、解析、开发等使用。将读取到的汽车内部运行数据通过手机APP软件直观展现。 首先大致梳理下车联网行业的特性有哪些: 1ã 月活非常高,在线时间长 车联网行业用户的月活是非常高的,这个很好理解,因为汽车现在人们出行的必备交通工具,基本上只要
- 下一篇
我来悟微服务(3)-需求管理
无限合并 最近工作上接到一个需求模块:关于账号自动合并的问题。简化来讲,手机1和邮箱1是一个账号,手机1和邮箱2请求过来创建账号时,由于手机号相同,自动合并为一个账号。手机3和邮箱2再过来请求创建账号,由于邮箱相同,自动合并为一个账号。手机3和邮箱4过来请求创建账号时,又因为手机号相同,再次合并为一个账号……假如是个访问量很大并且又这么巧的时候,就类似于无限合并了。实际上可能仅会出现几笔,不会这样无限循环下去。但我是一个容易多想的人。账号合并,又关联着和账号相关的数据的迁移,从我个人的角度来说,这样没有边界防御的需求,我内心是拒绝的,但还没想好更好的办法,暂且如此了。 这个话题联想到微服务,微服务能解决这种问题么?很遗憾,微服务并不是想象中的那么强大。账号合并本质上可以做成一个微服务,但微服务并不能解决这种业务问题。 我认识的微服务是为了方便水平扩展,方便使用体验异构技术,方便快速试错,方便部署,能最终实现高可用高并发。你了解再多的微服务知识,也不是用于解决此类业务问题。 对于此类业务问题,一般方式是判断需求是否合理?不合理的需求可以适当拒绝掉。 再着看是谁提的?如果是普通客户,尽量用...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- 2048小游戏-低调大师作品
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Mario游戏-低调大师作品
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS6,CentOS7官方镜像安装Oracle11G
- Docker使用Oracle官方镜像安装(12C,18C,19C)