自定义保持活动功能后站点停止工作
Site stops working after custom keep alive functionality
我最近部署了一个在共享主机环境中运行的站点。问题是站点收到零星的流量:20 分钟后,我想服务器关闭了实例,因此当站点加载第一个请求时,它通常很慢。所以我决定添加一个每隔几分钟加载一次网页的功能。我用 new CodeKeepAlive.KeepAliveManager().SetKeepAlive();
调用 Global.asax 中的代码,这是完整的代码:
public class KeepAliveManager
{
Timer KeepAliveTimer;
public void SetKeepAlive()
{
KeepAliveTimer = new Timer(DoKeepAliveRequest, null, new Random().Next(200000, 900000), Timeout.Infinite);
}
public void DoKeepAliveRequest(object state)
{
string TheUrl = "https://www.the_website_url.com";
HttpWebRequest TheRequest = (HttpWebRequest)WebRequest.Create(TheUrl);
HttpWebResponse TheResponse = (HttpWebResponse)TheRequest.GetResponse();
KeepAliveTimer.Change(new Random().Next(200000, 900000), Timeout.Infinite);
}
}
由于某种原因,自从我添加了此功能后,该站点有时会锁定;加载时间 30 秒后,服务器说无法加载页面。我还有一个在 Application_Error
上触发的错误记录功能,但没有日志。
我的代码有问题吗?
问题在于 asp.net 没有可靠的方法来 运行 后台任务而不会有 IIS 杀死线程的风险。一旦请求完成,IIS 就没有理由让您产生的任何线程保持活动状态。
有几种方法可以做到这一点,例如使用亚马逊免费层上的一些简单服务或 google 云作为您的心跳。
但假设您只想使用共享主机
您可以使用类似 HangFire
的工具,它专门用于此,但它们有其局限性,请参阅 docs for getting started:
GlobalConfiguration.Configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage("Database=Hangfire.Sample; Integrated Security=True;", new SqlServerStorageOptions
{
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
UsePageLocksOnDequeue = true,
DisableGlobalLocks = true
})
.UseBatches()
.UsePerformanceCounters();
//Queue the job
BackgroundJob.Enqueue(() => Console.WriteLine("Hello, world!"));
//run it
using (var server = new BackgroundJobServer())
{
Console.ReadLine();
}
注意: Hang Fire 它本身有其局限性 IIS 将关闭任何长的 运行ning 线程,例如需要超过 90 或 180 秒的事情(我忘记限制)所以确保你queue你的心跳任务对每个进来的请求。如果你想确保你不会触发太多,你可以在请求中添加一个header并且验证它是否在请求中。
在新 .Net-Core Background Tasks 上查看此答案,该答案适用,因为它与 IIS
相关
在 PhantomJs 中添加一个测试程序,以随机或定期截取 url 的屏幕截图并将其部署在同一台服务器上。
IT 将为您完成这项工作
我最近部署了一个在共享主机环境中运行的站点。问题是站点收到零星的流量:20 分钟后,我想服务器关闭了实例,因此当站点加载第一个请求时,它通常很慢。所以我决定添加一个每隔几分钟加载一次网页的功能。我用 new CodeKeepAlive.KeepAliveManager().SetKeepAlive();
调用 Global.asax 中的代码,这是完整的代码:
public class KeepAliveManager
{
Timer KeepAliveTimer;
public void SetKeepAlive()
{
KeepAliveTimer = new Timer(DoKeepAliveRequest, null, new Random().Next(200000, 900000), Timeout.Infinite);
}
public void DoKeepAliveRequest(object state)
{
string TheUrl = "https://www.the_website_url.com";
HttpWebRequest TheRequest = (HttpWebRequest)WebRequest.Create(TheUrl);
HttpWebResponse TheResponse = (HttpWebResponse)TheRequest.GetResponse();
KeepAliveTimer.Change(new Random().Next(200000, 900000), Timeout.Infinite);
}
}
由于某种原因,自从我添加了此功能后,该站点有时会锁定;加载时间 30 秒后,服务器说无法加载页面。我还有一个在 Application_Error
上触发的错误记录功能,但没有日志。
我的代码有问题吗?
问题在于 asp.net 没有可靠的方法来 运行 后台任务而不会有 IIS 杀死线程的风险。一旦请求完成,IIS 就没有理由让您产生的任何线程保持活动状态。
有几种方法可以做到这一点,例如使用亚马逊免费层上的一些简单服务或 google 云作为您的心跳。
但假设您只想使用共享主机
您可以使用类似 HangFire
的工具,它专门用于此,但它们有其局限性,请参阅 docs for getting started:
GlobalConfiguration.Configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage("Database=Hangfire.Sample; Integrated Security=True;", new SqlServerStorageOptions
{
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
UsePageLocksOnDequeue = true,
DisableGlobalLocks = true
})
.UseBatches()
.UsePerformanceCounters();
//Queue the job
BackgroundJob.Enqueue(() => Console.WriteLine("Hello, world!"));
//run it
using (var server = new BackgroundJobServer())
{
Console.ReadLine();
}
注意: Hang Fire 它本身有其局限性 IIS 将关闭任何长的 运行ning 线程,例如需要超过 90 或 180 秒的事情(我忘记限制)所以确保你queue你的心跳任务对每个进来的请求。如果你想确保你不会触发太多,你可以在请求中添加一个header并且验证它是否在请求中。
在新 .Net-Core Background Tasks 上查看此答案,该答案适用,因为它与 IIS
相关在 PhantomJs 中添加一个测试程序,以随机或定期截取 url 的屏幕截图并将其部署在同一台服务器上。 IT 将为您完成这项工作