adam78
adam78

Reputation: 10068

ASP MVC 5 Keep Site Alive

Currently I have a job to check and send out emails every minute. I'm using hangfire as the job scheduler but it requires the site to be kept alive in order to function properly. To work round this I'm using another job which runs every 5 minutes as follows to keep the site alive:

 public static bool Ping()
 {
        try
        {
             var request = (HttpWebRequest)WebRequest.Create('http://xyz.domain.com');
            request.Timeout = 3000;
            request.AllowAutoRedirect = false; // find out if this site is up and don't follow a redirector
            request.Method = "HEAD";

            using (request.GetResponse())
            {
                return true;
            }
        }
        catch
        {
            return false;
        }
}

Anyone know of any better or more efficient way to keep the site alive aside from using a windows service or task scheduler?

Upvotes: 2

Views: 1757

Answers (2)

Alex
Alex

Reputation: 38519

As you've noticed, app pool recycling, or application inactivity will cause recurring tasks and delayed jobs to cease being enqueued, and enqueued jobs will not be processed.

If you're hosting the application 'on premise' you can use the 'Auto Start' feature that comes with Windows Server 2008 R2 (or later) - running IIS 7.5 (or above)

Full setup instructions are on the Hangfire documentation - http://docs.hangfire.io/en/latest/deployment-to-production/making-aspnet-app-always-running.html

I'll summarise below.

1)
Create a class that implements IProcessHostPreloadClient

public class ApplicationPreload : System.Web.Hosting.IProcessHostPreloadClient
{
    public void Preload(string[] parameters)
    {
        HangfireBootstrapper.Instance.Start();
    }
}

2)
Update your global.asax.cs

public class Global : HttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        //note - we haven't yet created HangfireBootstrapper
        HangfireBootstrapper.Instance.Start();
    }

    protected void Application_End(object sender, EventArgs e)
    {
        HangfireBootstrapper.Instance.Stop();
    }
}

3)
Create the HangfireBootstrapper class mentioned above.

public class HangfireBootstrapper : IRegisteredObject
{
    public static readonly HangfireBootstrapper Instance = new HangfireBootstrapper();

    private readonly object _lockObject = new object();
    private bool _started;

    private BackgroundJobServer _backgroundJobServer;

    private HangfireBootstrapper()
    {
    }

    public void Start()
    {
        lock (_lockObject)
        {
            if (_started) return;
            _started = true;

            HostingEnvironment.RegisterObject(this);

            GlobalConfiguration.Configuration
                .UseSqlServerStorage("connection string");
                // Specify other options here

            _backgroundJobServer = new BackgroundJobServer();
        }
    }

    public void Stop()
    {
        lock (_lockObject)
        {
            if (_backgroundJobServer != null)
            {
                _backgroundJobServer.Dispose();
            }

            HostingEnvironment.UnregisterObject(this);
        }
    }

    void IRegisteredObject.Stop(bool immediate)
    {
        Stop();
    }
}

4)
Enable service auto-start

After creating above classes, you should edit the global applicationHost.config file (%WINDIR%\System32\inetsrv\config\applicationHost.config). First, you need to change the start mode of your application pool to AlwaysRunning, and then enable Service AutoStart Providers.

<applicationPools>
    <add name="MyAppWorkerProcess" managedRuntimeVersion="v4.0" startMode="AlwaysRunning" />
</applicationPools>

<!-- ... -->

<sites>
    <site name="MySite" id="1">
        <application path="/" serviceAutoStartEnabled="true"
                              serviceAutoStartProvider="ApplicationPreload" />
    </site>
</sites>

<!-- Just AFTER closing the `sites` element AND AFTER `webLimits` tag -->
<serviceAutoStartProviders>
    <add name="ApplicationPreload" type="WebApplication1.ApplicationPreload, WebApplication1" />
</serviceAutoStartProviders>

Note that for the last entry, WebApplication1.ApplicationPreload is the full name of a class in your application that implements IProcessHostPreloadClient and WebApplication1 is the name of your application’s library. You can read more about this here.

There is no need to set IdleTimeout to zero – when Application pool’s start mode is set to AlwaysRunning, idle timeout does not working anymore.

Upvotes: 0

Tomasz Kowalczyk
Tomasz Kowalczyk

Reputation: 1923

In last week for the same purpose I used an Azure Scheduler. I think it is very nice tool, you can:

  • schedule a job,
  • defince an action
  • get access to history of your scheduled task
  • etc.

So if you have an MSDN subscription I think it is worthly to consider.

Upvotes: 1

Related Questions