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文件,找到应用程序的入口点. 本 文 ...
随机推荐
- php中的XML DOM(11)
7.创建节点 在dom操作中,增删改操作必须要找父节点 1.DOMElement DOMDocument::createElement ( string $name [, string $value ...
- php socket 简单理解
以下内容转自:https://www.cnblogs.com/loveyoume/p/6076101.html 和 https://www.cnblogs.com/WuNaiHuaLuo/p/6107 ...
- Python面向对象(构造方法)
day24 构造方法 特殊作用:在obj=classname()中1.创建对象,2.通过对象执行类中的一个特殊方法. class Bar: def __init__(self): ") de ...
- javascript IE事件处理及跨浏览器事件处理程序
一.javascript事件处理中 addEventListener/removeEventListener 用于绑定事件和解除事件,但大多用于chrome/火狐/IE9这些比较高级的浏览器中,IE8 ...
- linux防火墙(五)—— 防火墙的规则备份与还原
一.第一种备份还原用法,使用工具 iptables-save >/opt/iprules.txt iptables-restore < /opt/iprules.txt #注意导入的文件必 ...
- 封装 原生 fetch
1, 简介 fetch方法是 Fetch API的一个方法,提供了一种简单.合理的方式来跨网络异步获取资源. 与原来的XMLHttpRequest比较,fetch更容易与其他的技术结合:比如servi ...
- /usr/bin/ld: cannot find -lperconaserverclient_r 解决
编译sqladvisor安装遇到: [root@localhost sqladvisor]# cd SQLAdvisor/sqladvisor/ [root@localhost sqladvisor] ...
- 布局优化之ViewStub、Include、merge使用分析
布局技巧 在Android开发过程中,我们会遇到很多的问题,随着UI界面越来越多,布局的重复性.复杂度也随之增加,所幸的是,Android官方也给出了几个对布局进行优化的方法,下面根据自己的理解对官方 ...
- 在windows上部署使用Redis--资料整理
声明:一下只是针对windows系统,其他系统资料需自己补全. 很简单:下载.安装.安装桌面管理工具.测试.细不具表,下面几个网址应该足以解决你的所有问题. 网址访问专用Host: http://pa ...
- SPSS学习系列之SPSS Statistics导入读取数据(多种格式)(图文详解)
不多说,直接上干货! SPSS Statistics导入读取数据的步骤: 文件 -> 导入数据 成功! 欢迎大家,加入我的微信公众号:大数据躺过的坑 免费给分享 同时,大 ...