最近,我们干了一件“惊天动地”的事——对改了十年、代码混乱无比、WebForms与MVC混血、ADO.NET与Entity Framework混合的博客程序,用.NET 4.5的async/await特性进行了异步化改造。主要的异步化改造已于昨天完成,并在昨天晚上发布了异步化改造后的博客程序。

触动我们进行这次异步化改造的是ASP.NET官网上一篇文章(Using Asynchronous Methods in ASP.NET 4.5)中的一段话:

A web application  using synchronous methods to service high latency calls where the thread pool grows to the .NET 4.5 default maximum  of 5, 000 threads would consume approximately 5 GB more memory than an application able the service the same requests using asynchronous methods and only 50 threads.

在高延迟操作场景下,同步方式需要5000个线程才能完成的工作,采用异步方式只需50个线程!以一敌百,如此的高效,怎能不让人心动。

而itworld一篇文章中的一句话更是火上浇油,让我们下定决心实现异步化。

I’ve seen load tests show 300% improvement in response times and concurrent connections boost almost 8x over the synchronous counterparts.

此次异步化改造一共有6个部分,其中三个部分的改造最轻松,它们是MVC,EF,WCF;而另外三个则最艰苦,它们是WebForms,ADO.NET,EnyimMemcached(memcached .NET客户端)。

下面分别简单介绍一下这6个部分的改造:

1. MVC的异步化改造

无比轻松,只要把ActionResult改为async Task<AstionResult>:

public async Task<ActionResult> SiteHome(int? pageIndex)
{//...
}

2. Entity Framework的异步化

也很轻松,查询时只需使用异步LINQ:

public async Task<int> GetAsync()
{return await Entities.Where(...).Select(...).CountAsync();
}

保存时只需SaveChangesAsync():

async Task IUnitOfWork.CommitAsync()
{await base.SaveChangesAsync();
}

3. WCF客户端的异步化

照样轻松,只要选择“Generate task-based operations”重新生成WCF客户端代理:

4. WebForms的异步化

a) 所有实现异步的.aspx都要加上async="true"标记。

<%@ Page Async="true" Language="c#"%>

b) 原来获取数据进行绑定的代码要放在异步方法中,并通过Page.RegisterAsyncTask进行注册。

protected override void OnLoad(EventArgs e)
{base.OnLoad(e);this.Page.RegisterAsyncTask(new System.Web.UI.PageAsyncTask(GetPostsByMonth));
}

c) 原来静态绑定的用户控件不得不改为动态加载。

同步时代:

<%@ Register TagPrefix="uc1" TagName="EntryList" Src="EntryList.ascx" %>
<uc1:EntryList id="Days" DescriptionOnly = "true" runat="server"></uc1:EntryList>

异步时代:

public  class ArchiveMonth : UserControl
{protected override void OnLoad(EventArgs e){base.OnLoad(e);this.Page.RegisterAsyncTask(new System.Web.UI.PageAsyncTask(GetPostsByMonth));}private async Task GetPostsByMonth(){        var DaysControl = LoadControl("EntryList.ascx") as EntryList;if (DaysControl != null){DaysControl.EntryListItems = await postSevice.GetEntriesByMonth(CurrentBlog, dt, PostType.BlogPost);DaysControl.DescriptionOnly = true;Controls.Add(DaysControl);}}
}

d) 原来在OnPreRender中的处理代码(依赖异步任务的处理结果)需要移至Render,因为ASP.NET是在OnPreRender阶段检查所有注册的异步任务并进行异步执行。

【WebFoms中的异步原理】

如果在.aspx中设置了async="true",ASP.NET线程在处理针对这个页面的请求时,会在PreRender阶段查找是否有注册的异步任务(async task);如果有,该线程会将当前请求放回队列中,然后抽身去处理其它请求。当异步任务完成时,该请求会被线程池中的某个线程捡起,直到执行完成。(参考自Async Pages part 2: How to use asynchrony in your Pages)。

5. ADO.NET的异步化

所有进行异步化的数据库操作都需要用类似下面的ADO.NET代码进行改造

using(var conn = new SqlConnection(connectionString))
{using(var command = conn.CreateCommand()){command.CommandType = CommandType.StoredProcedure;command.CommandText = "...";command.Parameters.AddWithValue("...", ...);await conn.OpenAsync();using (IDataReader reader = await command.ExecuteReaderAsync()){//...
        }}
}

6. EnyimMemcached的异步化

也就是Socket的异步化,参考msdn博客中的博文Awaiting Socket Operations,修改了EnyimMemcached,实现了Memcached客户端的异步化,修改后的代码已发布至github(https://github.com/cnblogs/EnyimMemcached)。

public async Task<IGetOperationResult<T>> GetAsync<T>(string key)
{//...            var commandResult = await node.ExecuteAsync(command);//...
}

【发布后的不理想情况】

1. CPU出现抖动

异步化改造后的博客程序发布后,在阿里云云服务器上CPU出现抖动,后来发展为疯狂抖动。

最后放弃使用异步化的EnyimMemcached,改回原来同步的EnyimMemcached,CPU抖动情况得到了改善(后来发现异步化后的EnyimMemcached存在内存泄漏问题)。

a) 访问低峰时的CPU抖动情况

b)访问高峰时的CPU抖动情况

2. w3wp进程消耗的线程与内存更多

这个地方的表现让人大跌眼镜,原以为线程与内存的消耗会明显降低,实际却不但不降反而上升。

【更新1】

我们在负载均衡中加了另外一台云服务器,不理想情况竟然没出现。

后来,我们将原先2台表现不理想的服务器中的w3wp进程重启后,不理想情况也消失了。昨天我们发布时只是更新了dll,并没有对w3wp进程进行回收。

【更新2】

重启w3wp进程之后,还是会出现CPU抖动的情况,但目前观测下来对响应速度未造成影响。我们猜测CPU抖动可能与并行处理有关。

【更新3】

解决进展:

1. 发现一个异步方法中调用了System.Web.HttpContext.Current,去掉了这个调用。

2. 增加ConfigureAwait(false)的使用。

【参考资料】

Best Practices in Asynchronous Programming

Using Asynchronous Methods in ASP.NET 4.5

Async Pages part 2: How to use asynchrony in your Pages

How to create Asynchronous device Page in ASP.NET 4.5

Why you should use async tasks in .NET 4.5 and Entity Framework 6?

Awaiting Socket Operations

转载于:https://www.cnblogs.com/cmt/p/aspnet_async_await.html

走进异步世界:博客程序的异步化改造以及发布后的不理想情况相关推荐

  1. 国内免费Blog博客程序评测(含ASP/PHP/.net)

    国内免费Blog博客程序评测(含ASP/PHP/.net) 开篇 之 向国内单用户博客程序开发者及使用者致敬 这些天一直在更换试用各种博客程序,从ASP的PJBlog到PHP的SaBlog-X,在本地 ...

  2. php个人博客程序推荐,推荐五款不错的个人博客程序

    前前后后接触过了5种个人博客程序,有ASP也有PHP,按接触的顺序进行排列如下:Pjblog.Z-blog.Wordpress.Sablog.Bo-blog,下面就谈谈个人对这些博客程序的认识,由于认 ...

  3. 常见博客程序的市场有这几个

    常见博客程序 随着互联网的火热发展,越来越多的人搭建属于自己的个人博客.在说说建站那些事一文中提到建立博客网站的三要素是:域名.服务器.博客程序,对于博客程序,可以自己写一个博客系统(如果你足够牛逼的 ...

  4. 网站建设(5)——博客程序的选择和部署

    常见博客程序 随着互联网的火热发展,越来越多的人搭建属于自己的个人博客.在说说建站那些事一文中提到建立博客网站的三要素是:域名.服务器.博客程序,对于博客程序,可以自己写一个博客系统(如果你足够牛逼的 ...

  5. 使用 vue + thinkjs 开发博客程序记录

    一入冬懒癌发作,给自己找点事干.之前博客程序写过几次,php 的写过两次,nodejs 用 ThinkJS 写过,随着 ThinkJS 版本从1.x 升级到 2.x 之前的博客程序也做过升级.但是因为 ...

  6. 用node.js 搭建的博客程序心得(node.js实战读书笔记1)

    学习node已经有一段时间了,之前把了不起的node.js看完了,基本算了解了一些node的基本的用法还有一些概念了,然后就开始看第二本node.js实战,第一章就是搭建一个博客程序.但是不得不吐槽一 ...

  7. php blog 博客程序那个好

    PHP blog 博客程序是现在很多站长和个人博客爱好者使用的程序,php blog 博客程序相对于asp blog 博客程序而言更加安全,快捷.收到了很多站长的追捧.下面郑州网站建设专家张旭为你推荐 ...

  8. 10种最流行的国外博客程序

    所以很多国外博客程序都被广泛使用,比如wordpress,joomla等.这些博客除了本身的程序外,也会提供许多插件.因此如何选择好适合自己的博客程序就很重要. 本文将会例举10款目前最流行的国外博客 ...

  9. 【翻译加转载】自己开发Blog博客程序:关于MetaWeblogAPI 的实现

    前言 最近想自己做一个Blog程序玩一下,自己做的博客程序,当然要能够和各种博客的客户端要能够连接起来才行. 想要连接当然就是要按照标准来做,目前流行的API主要有: MetablogAPI (博客园 ...

最新文章

  1. gem是什么证书_什么是GIA钻石?
  2. CVPR 2020 开源论文 | 多种可能性行人未来路径预测
  3. 如何在windows下使用linux命令
  4. 论OD最原始的用途------找程序BUG
  5. Spring Cloud sleuth with zipkin over RabbitMQ教程
  6. chrome和safari_私人浏览器-如何在Chrome和Safari中使用隐身模式
  7. 查看回调函数执行在那个线程中的方法
  8. 与中石油分享SOA成功实践
  9. JEECG弹出表单调用列表刷新
  10. Java中无法到达的语句
  11. mount failed: mount failed: exit status 1
  12. Windows 中使用苹果 macOS 动态桌面壁纸
  13. ZipEntry 类,zip的压缩与解压
  14. flutter 应用 adb shell input swipe 命令失效
  15. maya2020 redshift3.0.31demo版安装方法。
  16. php微信绑定银行卡_微信开发企业支付到银行卡PHP
  17. 下面有9个点的图片。你能一笔画出4条直线连接着9个点,并且不重复任何一条线吗?
  18. 修改Linux时间一般涉及到3个命令: date, clock, hwclock
  19. 数学问题(四)——素数
  20. centos yum配置文件 .repo文件解释

热门文章

  1. 你绝对想不到R文件找不到(cannot resolve symbol R)的原因
  2. sql中exists替换in的区别
  3. 快春运了,做个火车余票查询接口,余票来源12306,图是百度地图
  4. 20佳带给你灵感的优秀个人博客设计案例
  5. !Important:CSS中!important的作用用于Ie6.0 与Ie7.0、firefox
  6. 让你的JXTA应用更加安全.建立真正你自己的私有的组!
  7. swift:创建表格UITableView
  8. [转载] 七龙珠第一部——第002话 布玛没有尾巴
  9. Deep learning:十九(RBM简单理解)
  10. 访问控制管理的积极意义案例