背景

  已经有很多文章记录了 web程序中采用异步编程的优势和.Net异步编程的用法, 异步编程虽然不能解决查询数据库的瓶颈, 但是利用线程切换,能最大限度的弹性利用工作线程, 提高了web服务的响应能力。

  【 9012年了,再不会异步编程你是真老了】

本文要说的是利用取消机制缓解后台的查询瓶颈,开发者只需在 MVC/WebAPI查询方法体内关注CancellationToken并适时取消异步任务, 这将大大提高应用的响应能力。

头脑风暴

  想象你请求某网站页面,该页面正闪着菊花试图努力绽放(正在加载),最终你忍不了:

① F5刷新

② 转向其他页面

③ 点击浏览器“停止”按钮

对于可怜的服务器,用户快速刷新5次,服务器将被迫接受 5倍的工作量,这是因为即使用户刷新了浏览器(或点击停止按钮), 虽然取消了原始浏览器请求,但是Web服务器并不Care,仍然按部就班处理进入HTTP pipeline的请求(MVC/WebAPI 中默认行为),其他②③场景类似。

在异步编程中能向任务发出Cancellation信号,停止web服务器一切后端查询行为。

(此处更正,不应强调异步编程,能否发送取消信号是客户端决定,服务端要做的是准备好信号接收器CancellationToken, 也就是说本文的取消机制对异步、 同步均有效)

在.NET中,这是使用CancellationToken完成的。

  • 取消令牌的实例传递到异步任务

  • 异步任务监视令牌,以查看请求是否已经被取消。

  • 如果请求取消,则应停止执行正在执行的操作。.NET中的大多数异步方法将具有接受取消令牌的重载。

本文所说的请求是,耗时长的服务端读取查询(返回数据但不修改数据的查询)。取消已修改数据的请求对于用程序可能不是一个好的选择:

-  是否真的要因用户导航到应用程序中的另一个页面而取消保存?也许可以,但也可能不会。

-  除了数据问题,这也不会提高性能,因为数据库服务器将需要回滚该事务,这可能是一项昂贵的操作。

ASP.NET Core实践

监测CancellationToken令牌

  访问 MyReallySlowReport页面,等待5s,最终他们放弃了,去了其他页面:

所有正在进行的请求都将被取消。

MVC/WebAPI能接受到取消请求的信号。开发者只需要在Controller Action中添加CancellationToken参数,并在后续行为中监测该取消信号。

浏览器取消请求时,ASP.NET Core根据CancellationTokenModelBinder自动将HttpContext.RequestAborted这个token绑定到Action的CancellationToken 参数,CancellationTokenModelBinder将会在调用AddMvc()或services.AddMvcCore()时被注入。​

public async Task<ActionResult> MyReallySlowReport(CancellationToken cancellationToken)
{
List<ReportItem> items;
using (ApplicationDbContext context = new ApplicationDbContext())
{
items = await context.ReportItems.ToListAsync(cancellationToken);
}
return View(items);
}

很容易取消SQL的查询行为,因为上述EF的调用api支持取消异步操作; 对于自定义的长耗时查询行为,可以使用CancellationToken的原生触发用法:

public async Task<ActionResult> MyReallySlowReport(CancellationToken cancellationToken)
{
List<ReportItem> items;
using (ApplicationDbContext context = new ApplicationDbContext())
{
items = await context.ReportItems.ToListAsync(cancellationToken);
} foreach (var item in items)
{
cancellationToken.ThrowIfCancellationRequested();
// slow non-cancellable work
Thread.Sleep();
}
return View(items);
}

从以上代码也可推断出: CancellationToken 适用于同步方法。

处理取消操作抛出的异常

Web服务器触发取消信号,一般会向上会抛出 OperationCanceledException 或者 TaskCancellationException,所以为了记录这种非常规异常,建议采用独立的ExceptionFilter记录。

public class OperationCancelledExceptionFilter : ExceptionFilterAttribute
{
private readonly ILogger _logger; public OperationCancelledExceptionFilter(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<OperationCancelledExceptionFilter>();
}
public override void OnException(ExceptionContext context)
{
if(context.Exception is OperationCanceledException)
{
_logger.LogInformation("Request was cancelled");
context.ExceptionHandled = true;
context.Result = new StatusCodeResult();
}
}
}

SPA应用

以上是后端程序员利用 取消机制 缓解后台性能压力,针对的是浏览器触发的取消操作。 从web请求的产生来源分析,除了浏览器能发起请求, 编程也可以发起请求

>  想想日益常见的SPA程序(单页面程序),绝大部分页面请求都是ajax请求,你点击应用的另外一个“页面(JS代码维护页面导航),浏览器不会自动取消请求。

在SPA应用中,前端发起的ajax请求, 若要取消,是需要以编程方式取消的。

所以我墙裂建议, 在2C的SPA应用中,切换“页面“”时请 终止原页面的所有ajax请求。

var xhr = $.get("/api/myslowreport", function(data){
//show the data
}); //If the user navigates away from this page
xhr.abort() 

总结输出

1. 利用取消机制的前置条件 在于 请求能够发出取消指令
2. 利用取消机制的关键在于监测取消令牌,并作出取消操作
3. 请求不但可以从浏览器发起,ajax也可以发起, 在SPA程序中极其常见,故取消机制需要关注SPA应用的ajax取消

That‘s all ,前后端程序猿通力配合, 应用的吞吐量和响应能力极大提升, CTO要给各位加薪了。

https://www.cnblogs.com/JulianHuang/p/10678887.html

https://www.cnblogs.com/JulianHuang/p/10572840.html

[干货]AspNetCore熟练应用CancellationToken,CTO会对你刮目相看的更多相关文章

  1. 【Azure 微服务】Service Fabric中微服务在升级时,遇见Warning - System.Collections.Generic.KeyNotFoundException 服务无法正常运行

    问题描述 使用.Net Framework 4.5.2为架构的Service Fabric微服务应用,在升级后发布到Azure Fabric中,服务无法运行.通过Service Fabric Expl ...

  2. Android学习路线总结,绝对干货

    title: Android学习路线总结,绝对干货 tags: Android学习路线,Android学习资料,怎么学习android grammar_cjkRuby: true --- 一.前言 不 ...

  3. 记录我这一年的技术之路(nodejs纯干货)

    2015年12月28日23:19:54 更新koa应用.学习型网站和开发者工具等 coding伊始 开始认认真真的学习技术还是2015.10.21日开始的,记得很清楚,那天,是我在龙湖正式学习的第一天 ...

  4. IT技术学习指导之Linux系统入门的4个阶段(纯干货带图)

    IT技术学习指导之Linux系统入门的4个阶段(纯干货带图) 全世界60%的人都在使用Linux.几乎没有人没有受到Linux系统的"恩惠",我们享受的大量服务(包括网页服务.聊天 ...

  5. ASP.NET Core 源码阅读笔记(3) ---Microsoft.AspNetCore.Hosting

    有关Hosting的基础知识 Hosting是一个非常重要,但又很难翻译成中文的概念.翻译成:寄宿,大概能勉强地传达它的意思.我们知道,有一些病毒离开了活体之后就会死亡,我们把那些活体称为病毒的宿主. ...

  6. 优测优社区干货精选|老司机乱谈编辑器之神——vim

    文 / 腾讯 吴双 前言 优测小优 有话说: 腾讯优测只有应用测试大神?不不不,我们还有各种研发大牛! *** vim 是一种信仰,我自从2004年有了这个信仰,已经12个年头了.本文介绍了学习vim ...

  7. APP运营干货分享

    从移动互联网市场总监岗位出发,从几个方面来阐述移动互联网部门如何制定一份运营推广策划案,至于关于移动互联网,移动电商是大趋势这些虚的.空泛的文字,不展开说了. 一.竞品分析 1.选择竞品,做好定位(选 ...

  8. AspNetCore.Hosting

    Microsoft.AspNetCore.Hosting 有关Hosting的基础知识 Hosting是一个非常重要,但又很难翻译成中文的概念.翻译成:寄宿,大概能勉强地传达它的意思.我们知道,有一些 ...

  9. 6月27日CTO俱乐部下午茶印象

    作者:朱金灿 来源:http://blog.csdn.net/clever101 感谢CSDN的邀请,有幸参加了6月27日“CTO俱乐部下午茶时光:CTO在团队管理中所遇到的那些事”活动.本期的主讲嘉 ...

随机推荐

  1. Ubuntu18.04 安装 OpenCV 4.1.1

    1. 安装依赖包 sudo apt-get install build-essential sudo apt-get install cmake git libgtk2.0-dev pkg-confi ...

  2. Lombok中关于@Data的使用

    当你在使用 Lombok 的 @Data 注解时,其实会有一些坑需要关注,今天就让我们来见识一下. Lombok 先来简单介绍一下 Lombok ,其官方介绍如下: Project Lombok ma ...

  3. C# 委托 (一)—— 委托、 泛型委托与Lambda表达式

    C# 委托 (一)—— 委托. 泛型委托与Lambda表达式 2018年08月19日 20:46:47 wnvalentin 阅读数 2992   版权声明:此文乃博主之原创.鄙人才疏,望大侠斧正.此 ...

  4. 【websocket】spring boot 集成 websocket 的四种方式

    集成 websocket 的四种方案 1. 原生注解 pom.xml <dependency> <groupId>org.springframework.boot</gr ...

  5. Qualcomm-Atheros-QCA9377-Wifi-Linux驱动

    资源来自:https://download.csdn.net/download/ichdy/10331646 已经下载好了,发现无法使用,本人系统Centos7.2,如果有安装成功,并且可以正常使用的 ...

  6. 实战SpringCloud响应式微服务系列教程(第八章)构建响应式RESTful服务

    本文为实战SpringCloud响应式微服务系列教程第八章,讲解构建响应式RESTful服务.建议没有之前基础的童鞋,先看之前的章节,章节目录放在文末. 1.使用springboot2.1.4构建RE ...

  7. python-写入文件

    一.写入空文件(覆盖) # coding=UTF-8 filename = 'test_text.txt' with open(filename, 'w') as file_object: file_ ...

  8. Java基础(42)AbstractSet类

    AbstractSet类的子类有HashSet(其子类是LinkedHashSet).EnumSet.TreeSet 1.HashSet public class HashSet<E> e ...

  9. Computer English Notes

    Chapter 1 : About Computer Answer the following - Abbreviation LBS - Location-Based Services HTML - ...

  10. dom 创建时间

    下面讲述如何在页面生成一个装有日期的盒子 首先写出一个日期的函数进行赋值使用document.createElement创建一个文档节点div,然后将时间函数输出在div之中,利用document.b ...