.NET Core定时器提升IIS下站点的反应速度
问题
IIS下发布.NET Core网站,第一次访问或者过两分钟访问,要查询10秒以上,才返回结果。第二次快速访问就变快了。再过两分钟访问,依然要重新加载10秒以上。
分析原因
根据上述问题,经过多次测试,不间断访问,就不会有延迟,但客户往往不可能一直点击网站某个页面,所以请求肯定会是间断性发出的。那么每次加载10秒以上对客户很不友好。
一度怀疑两方面原因,第一是.Net Core自身机制,每次要重新加载好多服务。
第二是IIS有应用程序池自动回收的机制,检测不到程序运行就自动回收了,下次在访问重新加载。
那么以上两点串起来就是个耗时的操作。
解决方案
找了很多资料有说改IIS配置的,有热代码的,最终决定用一个简单粗暴的方式,定时器定时访问某个接口,模拟用户一直访问站点,这样IIS就不会做资源回收,反应速度也快很多
代码
//Startup.cs
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime applicationLeftTime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
//netcore start/end
applicationLeftTime.ApplicationStarted.Register(() =>
{
//里面可以写其他逻辑
//Console.Write("ApplicationStarted");
logger.Info("ApplicationStarted...");
//程序启动定时器启动,程序停止定时器也会停止
AppTimer.RunProgram().GetAwaiter().GetResult();
});
applicationLeftTime.ApplicationStopped.Register(() => {
//里面可以写其他逻辑
//Console.Write("ApplicationStopped");
logger.Info("ApplicationStopped...");
});
applicationLeftTime.ApplicationStopping.Register(() => {
//里面可以写其他逻辑
//Console.Write("ApplicationStopping");
logger.Info("ApplicationStopping...");
});
//app.UseHttpsRedirection(); //重定向https注释解君愁
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=QRCodeRecruitment}/{action=Index}/{id?}");
});
}
//AppTimer.cs
public class HelloJob : IJob
{
NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
public async Task Execute(IJobExecutionContext context)
{
//logger.Info("Greetings from HelloJob!");
//调用API使site保持被访问
}
}
public static class AppTimer
{
public static async Task RunProgram()
{
try
{
// Grab the Scheduler instance from the Factory
NameValueCollection props = new NameValueCollection
{
{ "quartz.serializer.type", "binary" }
};
StdSchedulerFactory factory = new StdSchedulerFactory(props);
IScheduler scheduler = await factory.GetScheduler();
// 启动任务调度器
await scheduler.Start();
// 定义一个 Job
IJobDetail job = JobBuilder.Create<HelloJob>()
.WithIdentity("job1", "group1")
.Build();
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create()
.WithIdentity("trigger1") // 给任务一个名字
.StartAt(DateTime.Now) // 设置任务开始时间
.ForJob("job1", "group1") //给任务指定一个分组
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(60) //循环的时间 1秒1次 IIS 60s内请求不耗时
.RepeatForever())
.Build();
// 等待执行任务
await scheduler.ScheduleJob(job, trigger);
// some sleep to show what's happening
//await Task.Delay(TimeSpan.FromMilliseconds(2000));
}
catch (SchedulerException se)
{
await Console.Error.WriteLineAsync(se.ToString());
}
}
}
这样定时器定时每60秒发一个post请求访问数据,模拟站点一直被访问,就不会出现两分钟重新加载耗时操作。亲测有效
仅供学习参考,如有侵权联系我删除