Orchard源码:热启动
概述
IIS线程池中的线程数量是有限制的。当有多个长时间请求时,可能会耗尽IIS可用线程。出现503错误。在MVC中。当遇到非CPU操作的长时间请求时,MVC提供了异步方法来解决这个问题。
例:利用async和await实现异步方法
// GET: Async [AsyncTimeout(1000)] public async Task<ActionResult> Index() { var data = await GetPageTaskAsync("http://www.baidu.com"); return data; }
回到Orchard,在Orchard启动时,需要一定时间加载模块插件,这时候如果出现大量请求,则有可能出现上面提到的错误。来看一下Orchard中是如何解决这个问题。
项目结构Orchard.WarmupStarter ,是一个单独的项目。方便复用
具体实现
一句话概括实现步骤: 启动时初始化一个异步请求列表,初始化期间有请求到来时,把该请求添加到请求列表中。当系统初始化完成时回调起步请求列表并且清空。
Starter.cs
/// <summary> /// Run the initialization delegate asynchronously in a queued work item /// </summary> public void LaunchStartupThread(HttpApplication application) { // Make sure incoming requests are queued WarmupHttpModule.SignalWarmupStart(); ThreadPool.QueueUserWorkItem( state => { try { var result = _initialization(application); _initializationResult = result; } catch (Exception e) { lock (_synLock) { _error = e; _previousError = null; } } finally { // Execute pending requests as the initialization is over WarmupHttpModule.SignalWarmupDone(); } }); } WarmupHttpModule.SignalWarmupStart(); 系统开始加载,初始化请求列表 public static void SignalWarmupStart() { lock (_synLock) { if (_awaiting == null) { _awaiting = new List<Action>(); } } } WarmupHttpModule.SignalWarmupDone(); 系统加载完成,回调请求列表并且清空 public static void SignalWarmupDone() { IList<Action> temp; lock (_synLock) { temp = _awaiting; _awaiting = null; } if (temp != null) { foreach (var action in temp) { action(); } } }
WebConfig中注册WarmupHttpModule
请求到来时,执行WarmupHttpModule.BeginBeginRequest回调, 如果加载中,则请求添加到异步列表,否则继续执行回调
private IAsyncResult BeginBeginRequest(object sender, EventArgs e, AsyncCallback cb, object extradata) { // host is available, process every requests, or file is processed if (!InWarmup() || WarmupUtility.DoBeginRequest(_context)) { var asyncResult = new DoneAsyncResult(extradata); cb(asyncResult); return asyncResult; } else { // this is the "on hold" execution path var asyncResult = new WarmupAsyncResult(cb, extradata); Await(asyncResult.Completed); return asyncResult; } }
异步编程模型 DoneAsyncResult 和 WarmupAsyncResult 实现IAsyncResult
WarmupAsyncResult
/// <summary> /// AsyncResult for "on hold" request (resumes when "Completed()" is called) /// </summary> private class WarmupAsyncResult : IAsyncResult { private readonly EventWaitHandle _eventWaitHandle = new AutoResetEvent(false/*initialState*/); private readonly AsyncCallback _cb; private readonly object _asyncState; private bool _isCompleted; public WarmupAsyncResult(AsyncCallback cb, object asyncState) { _cb = cb; _asyncState = asyncState; _isCompleted = false; } public void Completed() { _isCompleted = true; _eventWaitHandle.Set(); _cb(this); } bool IAsyncResult.CompletedSynchronously { get { return false; } } bool IAsyncResult.IsCompleted { get { return _isCompleted; } } object IAsyncResult.AsyncState { get { return _asyncState; } } WaitHandle IAsyncResult.AsyncWaitHandle { get { return _eventWaitHandle; } } }
DoneAsyncResult(不阻塞)
/// <summary> /// Async result for "ok to process now" requests /// </summary> private class DoneAsyncResult : IAsyncResult { private readonly object _asyncState; private static readonly WaitHandle _waitHandle = new ManualResetEvent(true/*initialState*/); public DoneAsyncResult(object asyncState) { _asyncState = asyncState; } bool IAsyncResult.CompletedSynchronously { get { return true; } } bool IAsyncResult.IsCompleted { get { return true; } } WaitHandle IAsyncResult.AsyncWaitHandle { get { return _waitHandle; } } object IAsyncResult.AsyncState { get { return _asyncState; } } }
总结
Orchard.WarmupStarter 已封装好相关热启动代码, 实际项目中如果初始化时间比较长,稍改造Orchard.WarmupStarter就可复用到自己的项目中。
参考
http://www.cnblogs.com/alby/archive/2012/10/18/orchard-WarmupStarter.html
Orchard源码:热启动的更多相关文章
- Orchard源码分析(5):Host相关(Orchard.Environment.DefaultOrchardHost类)
概述 Host 是应用程序域级的单例,代表了Orchard应用程序.其处理应用程序生命周期中的初始化.BeginRequest事件.EndRequest事件等. 可以简单理解为HttpApplicat ...
- Orchard 源码探索(Log)
简单工厂模式.抽象工厂模式和适配器模式 依赖倒置原则也叫依赖倒转原则,Dependence Inversion Principle,对抽象进行编程,不要对实现进行编程. A.高层次的模块不应该依赖于低 ...
- Orchard源码分析(7.1):Routing(路由)相关
概述 关于ASP.NET MVC中路由有两个基本核心作用,一是通过Http请求中的Url参数等信息获取路由数据(RouteData),路由数据包含了area.controller.action的名称等 ...
- Orchard源码分析(4.4):Orchard.Caching.CacheModule类
概述 CacheModule也是一个Autofac模块. 一.CacheModule类 CacheModule将DefaultCacheManager注册为ICacheManager: ...
- Orchard源码分析(6):Shell相关
概述在Orchard中,提出子站点(Tenant)的概念,目的是为了增加站点密度,即一个应用程序域可以有多个子站点. Shell是子站点(Tenant)级的单例,换句话说Shell代表了子站点.对比来 ...
- Orchard源码分析(5.1):Host初始化(DefaultOrchardHost.Initialize方法)
概述 Orchard作为一个可扩展的CMS系统,是由一系列的模块(Modules)或主题(Themes)组成,这些模块或主题统称为扩展(Extensions).在初始化或运行时需要对扩展进行安装:De ...
- Orchard源码分析(4.3):Orchard.Events.EventsModule类(Event Bus)
概述 采用Event Bus模式(事件总线),可以使观察者模式中的观察者和被观察者实现解耦. 在.Net 中使用观察者模式,可以使用事件(委托)和接口(类).Orchard Event Bus使用的 ...
- Orchard源码分析(4.1):Orchard.Environment.CollectionOrderModule类
CollectionOrderModule类是一个Autofac模块(Module,将一系列组件和相关的功能包装在一起),而非Orchard模块.其作用是保证多个注册到容器的组件能按FIFO(Firs ...
- Orchard源码分析(3):Orchard.WarmupStarter程序集
概述 Orchard.WarmupStarter程序集包含三个类:WarmupUtility.WarmupHttpModule和Starter<T>.该程序集主要为Orchard应用启动初 ...
- Orchard源码分析(2):Orchard.Web.MvcApplication类(Global)
概述 分析一个的ASP.NET项目源码,首先可以浏览其项目结构,大致一窥项目其全貌,了解项目之间的依赖关系.其次可以浏览Web.config和Global.asax文件,找到应用程序的入口点. 本 文 ...
随机推荐
- 虚拟化 - VMware
和VirtualBox一样,也需要关掉Hyper-V才能启动虚拟机,否则会报Guard的错误. 网络 [转]VMware网络连接模式-桥接.NAT以及仅主机模式的详细介绍和区别 桥接 就好像在局域网中 ...
- hud 5124 lines(思维 + 离散化)
http://acm.hdu.edu.cn/showproblem.php?pid=5124 lines Problem Description: John has several lines. ...
- AJPFX平台介绍
AJPFX设立于英国,业务框架扩展到欧洲.美洲和亚洲,在新加坡设有专门的亚洲地区服务部门.AJPFX旨在以极具竞争力的交易成本,也就是银行间市场核心点差和低水平的手续费,使客户在交易中获取最大的利润空 ...
- kolla-ansible 重新部署 ceph 遇到的问题
问题 TASK [ceph : Fetching Ceph keyrings] ******************************************* fatal: [controll ...
- Nmap 扫描
最近在家里学习渗透,看到了nmap对服务器进行端口扫描,记录学习如下: Nmap支持非常多的扫描方式,包括TCP Syn ,TCP Connect,TCP ACK,TCP FIN/Xmas/NULL, ...
- Java多线程编程 — 锁优化
阅读目录 一.尽量不要锁住方法 二.缩小同步代码块,只锁数据 三.锁中尽量不要再包含锁 四.将锁私有化,在内部管理锁 五.进行适当的锁分解 正文 并发环境下进行编程时,需要使用锁机制来同步多线程间 ...
- [bzoj4444] 国旗计划 双指针+倍增
Description A国正在开展一项伟大的计划--国旗计划.这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈.这项计划需要多名边防战士以接力的形式共同完成,为此,国土安全局已经挑选了N名优秀的边 ...
- bash脚本编程学习笔记(一)
bash脚本语言,不同于C/C++是一种解释性语言.即在执行前不需要事先转变为可执行的二进制代码,而是每次执行时经解释器解释后执行.bash脚本语言是命令的堆砌,即按照实际需要,结合命令流程机制实现的 ...
- jmeter 之 BeanShell PostProcessor跨线程全局变量使用
BeanShell PostProcessor是用户对一些变量的操作,操作方法很灵活,大概原理是通过parameters传回来对象,然后在script中对对象进行操作 场景:从登陆接口中获取token ...
- Stopwatch类学习
1.概述:给一条大MSDN的链接关于Stopwatch类最详细的教程 ,然后看着教程自己手动敲一边,加深映象,好记性不如烂键盘,哈哈,开个玩笑! 2.类位置:这个类在哪里,这个是重点,虽然C#IDE很 ...