How to get Hangfire started ("always on") in Azure shared hosting?
Asked Answered
S

3

6

I want to deploy a simple shared-host ASP.NET MVC site to Azure (using the free site option) which uses Hangfire to run scheduled tasks.

Problem is the site only starts on the first request, and so Hangfire doesn't start scheduling tasks until then. With IIS or a dedicated VM, you can set the "always on" option to prewarm the site. But this is not possible in shared hosting.

What can I do about this? I thought of paying for the smallest VM, called "A0", and putting a ping script on there to ensure my site is always up. That would work, but seems like overkill.

Are there any other good options?

Shifrah answered 5/11, 2014 at 10:35 Comment(3)
Have you considered using Azure Scheduler (azure.microsoft.com/en-us/services/scheduler) instead?Decasyllable
@Decasyllable The free option will only allow me to ping hourly. The cheapest paid option will do so every minute--but it costs the same as a VM, so a VM seems like more value. The MS marketing guys are super smart with their Azure pricing!Shifrah
@Decasyllable update for any new readers: Azure Scheduler is set to retire on 30th Sept 2019. MS recommend migration to LogicApps instead.Greenhead
S
4

If you still would like to use azure website you have to switch from SHARED to BASIC (that's the first one with ALWAYS ON option), but it's more than 3 times more expensive than the cheapest VM.

If I were you I would go for cheapest Cloud Service - Web Role. It cost a bit more than the cheapest VM but it's already configured for web sites and you don't have to set up everything on your own + you can use Visual Studio to deploy it, you can RDP to the box and many many more.

See http://azure.microsoft.com/en-us/pricing/details/cloud-services/ for pricing details.

But as suggested in comments Azure Schedule is something worth looking at.

UPDATE: (WARNING - interesting but completely not serious solution)

Use Azure Scheduler to ping you web page to keep it alive ;-) You can create up to 5 jobs with maximum execution every hour with FREE tier. Which means that you can create 5 jobs which will ping you website every 12 minutes.

Slenderize answered 5/11, 2014 at 11:27 Comment(7)
Yes I already noted that in the comments above. It is a good option, but I need more than 1 hour pings. And the cost is the same as just getting a small VM.Shifrah
You can use FREE tier and create 5 every-hour "ping" jobs: 00:00, 00:12, 00:24, 00:36 and 00:48 - which means you can have ping every 12 minutes (5 jobs). Pricing details azure.microsoft.com/en-gb/pricing/details/schedulerSlenderize
To be honest, this is so good, there is no need for Hangfire scheduler anymore. I'll just create a job that makes a request to an MVC action, which performs the scheduled action. I'm happy to have it every 12minutes!Shifrah
But of course, that means that anyone can access that action. Which is a security risk.... don't know what I'll do about that.Shifrah
You can use "POST" to avoid "accidental" browse to your action. It's still not secure. If you want to make sure that some action is executed only every x-minutes just save somewhere last execution time and check it when you MVC action is called. BTW: I hope you are not implementing any critical/production system.Slenderize
Its not critical, but I prefer that its not called more than once at a time--your timestamp idea is good, but locking the action is even better (though I'm wasting threads that way from the thread pool).Shifrah
Azure Scheduler is set to retire on 30th Sept 2019. MS recommend migration to LogicApps instead.Greenhead
O
7

Old question I know, but maybe I am missing something. I use UptimeRobot (https://uptimerobot.com/) as it continually makes request to your web server to keep it alive. Wouldn't that be much simpler than creating an automated job on your own. Again, I'm not sure if being on a shared environment would render UptimeRobot useless, but just a thought I wanted to pass along.

Orfinger answered 3/4, 2015 at 18:0 Comment(1)
Or pingdom.com. Same idea...just keep a heartbeat going and you'll be fine.Nadean
S
4

If you still would like to use azure website you have to switch from SHARED to BASIC (that's the first one with ALWAYS ON option), but it's more than 3 times more expensive than the cheapest VM.

If I were you I would go for cheapest Cloud Service - Web Role. It cost a bit more than the cheapest VM but it's already configured for web sites and you don't have to set up everything on your own + you can use Visual Studio to deploy it, you can RDP to the box and many many more.

See http://azure.microsoft.com/en-us/pricing/details/cloud-services/ for pricing details.

But as suggested in comments Azure Schedule is something worth looking at.

UPDATE: (WARNING - interesting but completely not serious solution)

Use Azure Scheduler to ping you web page to keep it alive ;-) You can create up to 5 jobs with maximum execution every hour with FREE tier. Which means that you can create 5 jobs which will ping you website every 12 minutes.

Slenderize answered 5/11, 2014 at 11:27 Comment(7)
Yes I already noted that in the comments above. It is a good option, but I need more than 1 hour pings. And the cost is the same as just getting a small VM.Shifrah
You can use FREE tier and create 5 every-hour "ping" jobs: 00:00, 00:12, 00:24, 00:36 and 00:48 - which means you can have ping every 12 minutes (5 jobs). Pricing details azure.microsoft.com/en-gb/pricing/details/schedulerSlenderize
To be honest, this is so good, there is no need for Hangfire scheduler anymore. I'll just create a job that makes a request to an MVC action, which performs the scheduled action. I'm happy to have it every 12minutes!Shifrah
But of course, that means that anyone can access that action. Which is a security risk.... don't know what I'll do about that.Shifrah
You can use "POST" to avoid "accidental" browse to your action. It's still not secure. If you want to make sure that some action is executed only every x-minutes just save somewhere last execution time and check it when you MVC action is called. BTW: I hope you are not implementing any critical/production system.Slenderize
Its not critical, but I prefer that its not called more than once at a time--your timestamp idea is good, but locking the action is even better (though I'm wasting threads that way from the thread pool).Shifrah
Azure Scheduler is set to retire on 30th Sept 2019. MS recommend migration to LogicApps instead.Greenhead
S
0

This answer comes late, but it saved me some hassle.

It is very similar to the previous answer https://mcmap.net/q/1667306/-how-to-get-hangfire-started-quot-always-on-quot-in-azure-shared-hosting and applies the same principle using Hangfire since it's already part of the app.

Use Azure Scheduler to ping you web page to keep it alive ;-) You can create up to 5 jobs with maximum execution every hour with FREE tier. Which means that you can create 5 jobs which will ping you website every 12 minutes.

I had to run a very simple site with Hangfire jobs in Azure that would do some processing. Scaling it up to a B plan or above just to have Always On was going to bee too pricey for this.

A workaround to keeping the app service always on in the Free tier was to create a scheduled Hangfire job that would run every 10 minutes after the site starts and ping itself.

Even if your app doesn't need Hangfire, you can just drop it in there for the sake of the scheduled job and use and event use InMemory storage to persist the job, as long as it pings the site every 10 minutes.

This will keep the app service warmed up and always on without exhausting the usage quota - the daily CPU time consumption of this is probably less than 10 seconds, which is well under the daily 60 minutes limit of the Free tier. DB DTU consumption is also very low in the case of an Azure SQL database.

Example job setup:

// Call this right after your app service starts.
RecurringJob.AddOrUpdate<PingJob>("Azure Always On", x => x.PingAsync("https://<yousite>.azurewebsites.net/"), "*/10 * * * *");

And the implementation of the PingJob, using package Flurl.Http to keep it super simple:

using Flurl.Http;

namespace YourAwesomeApp;

public class PingJob
{
    public Task PingAsync(string url) => url.GetAsync();
}
Sentient answered 22/10, 2023 at 11:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.