前言
项目中使用了Quartz.Net 作为任务调度框架,执行定时任务功能,任务的开始和结束放在Application_Start和Application_End中调用,因为IIS的应用程序池自动回收导致某些时间(无用户访问导致没有请求到Application_Start 触发任务开始)定时任务执行失败,下面对解决方式做一个记录。
方案一
修改IIS程序池的回收设置的 固定时间间隔和 进程模型的闲置超时 设置为0 (不推荐)
或者根据用户使用时间设置一个合理的回收时间间隔 如 用户可能下班后(18:00)不再访问站点,而夜间一点要执行一个定时作业,则设置闲置超时为8*60=480分钟
方案二
在站点中设置定时请求站点,不触发闲置超时,保证始终有请求发送到站点
/**Global.asax**/
private static string DummyPageUrl = ConfigurationManager.AppSettings["RefreshUrl"].ToString();//可访问的页面
private static string RefreshTime = ConfigurationManager.AppSettings["RefreshTime"].ToString();
private const string DummyCacheItemKey = "CallWebsite";
// 注册一缓存条目在RefreshTime分钟内到期,到期后触发的调事件 RefreshTime 要小于站点应用程序池的闲置超时时间
private void RegisterCacheEntry()
{
if (null != HttpContext.Current.Cache[DummyCacheItemKey]||!int.TryParse(RefreshTime,out int minute))
return;
HttpContext.Current.Cache.Add(DummyCacheItemKey, "r", null, DateTime.MaxValue,
TimeSpan.FromMinutes(minute), CacheItemPriority.NotRemovable,
new CacheItemRemovedCallback(CacheItemRemovedCallback));
}
// 缓存项过期时程序模拟点击页面,阻止应用程序结束
public void CacheItemRemovedCallback(string key, object value, CacheItemRemovedReason reason)
{
HitPage();
}
// 模拟点击网站网页
private void HitPage()
{
System.Net.WebClient client = new System.Net.WebClient();
client.DownloadData(DummyPageUrl);
}
protected void Application_Start()
//IIS超过空闲时间会回收导致定时停止,这里采用定时访问站点的方式,阻止站点进行回收
RegisterCacheEntry();
}
protected void Application_BeginRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.Request.Url.ToString() == DummyPageUrl)
{
RegisterCacheEntry();
}
}
<!--Web.config-->
<app key="RefreshUrl" value="localhost:9000/controller/action?refresh=1"/>
<app key="RefreshTime" value="19"/>
方案三
将任务调度框架做成Windows服务项目,安装到服务器上,定时请求API执行任务完成功能。
结语
以上就是解决IIS程序池定期回收导致定时作业不执行的方案了,如有问题还请指正。
附录
参考文章 c#解决应用池自动回收的方法