自定义保持活动功能后站点停止工作

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 将为您完成这项工作