8

I am working on an asp.net mvc-5 web application, deployed under windows 2012 & iis-8. my asp.net mvc have many CRUD operations which are implemented as action methods inside my asp.net mvc. But my asp.net mvc web application will be doing scheduled long running network scan process, the network scan will mainly do the following steps:-

  1. Get the list of our servers and vms from our database.
  2. Get the scanning username and password for each server and vm from a third party tool, using Rest API.
  3. Call some powershell scripts to retrieve the servers & vms info such as network info, memory, name, etc.
  4. Update our ERP system with the scan info using Rest API.

Now I did a pilot project using the following approach:-

  • I define a Model method inside my asp.net mvc to do the above 4 steps.
  • Then I install hangfire tool which will be calling the scan method on predefined scheduler.
  • Also I create a View inside my asp.net mvc which allow users to set the hangfire schedule settings (this require to do an IIS reset on the host server for hangfire to get the new settings).

Now I run a test scan for a round 150 servers which took around 40 minutes to complete , and it worked well. The only thing I noted is that if I set the schedule to run on non-business hours (where no activity is made on IIS) then hangfire will not be able to call the job, and once the first request is made the missed jobs will run. I overcome this limitation by defining a windows task which calls IIS each 15 minutes, to keep application pool live, and it worked well...

Now the other approach I am reading about is doing my above is as follow:-

  1. Instead of defining Model method inside asp.net mvc to do the scan, I can create a separate console application to do the scan.
  2. Then inside my asp.net mvc to create a view which allow users to create and schdule a task inside the windows tasks scheduler. I can do so by integrating with the windows task scheduler API.
  3. Where this windows task will be calling the console application.

Now I am not sure which approach is better and why ? now generally speaking long running/background jobs should not run under iis.. But at the same time defining these long running processes as console app and calling these apps inside windows task scheduler will create extra dependencies on my web application. And will add extra effort when moving the application from move server to another (for example from test to live).. Beside this I read that tools such as hangfire, quartz and other are designed to allow running long running tasks inside IIS and they eliminate the need to create console applications and scheduling these console applications using task scheduler .. So can anyone advice on this?

John John
  • 1
  • 72
  • 238
  • 501
  • 1
    And what about creating windows local service that will be running on your server and will communicate with your MVC app throug WCF, and for schedule jobs in this service use quartz.NET? – Marcin Feb 22 '16 at 12:57
  • @Marcin now quartz.net will be running under iis ,, so i will be facing the same problem,, that if i schedule the long running process during non-business hours then the application pool will not be running , so the background job will not fire... – John John Feb 22 '16 at 13:09
  • See my answer; Hangfire recommends to keep the application pool always running and to disable idle time-out. – ErikHeemskerk Feb 22 '16 at 13:19
  • @john G why quartz.net will be running under iis? You can create your own local service that will appear on that list here: `%windir%\system32\services.msc`and from there you can run your quartz.net jobs. I'm using this solutions for HID cards number synchronisation and it works well. This local services expose some methods through WCF. Long story short: local service works directly on phisical server and comunicates with my MVC app that is running on IIS – Marcin Feb 22 '16 at 14:24
  • @Marcin i did not work on similar thing before, so now you mean i need to move my scan business logic (which is currently defined inside my asp.net mvc action method) to be inside a windows service, then use quartz.net to call this service ? second question what will be the differences between this approach and between creating a console application and then use windows task scheduler to call the console application ?? – John John Feb 22 '16 at 15:57
  • 1
    *"long running/background jobs should not run under iis"* **CORRECT.** The correct architecture would be to have a console application scan your system and write your node list into a flat file or DB for your web app to read – Dave Alperovich Feb 22 '16 at 20:30
  • @DaveAlperovich ok thanks for the reply. Yes this what i am thinking of also. 1) to move my logic from being inside my asp.net mvc action method , to be inside a separate console application. the console app will update the DB, which will be read by my asp.net mvc. now this part is clear to me know. the only concern is how to schedule the console app execution, is using a web based scheduler an approach to follow such as hangfire or quartz, where these web schedulers (which run under iis) will be calling the console application? or it is better to use windows task scheduler? – John John Feb 23 '16 at 01:24
  • @DaveAlperovich ... .. now seems i can do so either using;1) web schedulers such as quartz.net or hangfire , OR 2)using windows task scheduler OR 3)seems quartz can be installed as a windows service inside my server,, so not sure which scheduler type i need to use or is better to use ? Baring in mind that i want to have a simple GUI inside my asp.net mvc to allow users to manage the schedule time , not sure if Windows task scheduler allow this sort of integration to schedule when its task should run? – John John Feb 23 '16 at 01:53
  • @john G there are no big diferencces between consol app and windows local service. Except that windows services by default can be always run and it manage by services and you consol app must be scheduled to do that. About your 'long time business logic' yuo can move it to windows service as quartz job. Quartz starts with service and manage its jobs. Configuration of quartz can be stroed in db or serialized to file so UI for manage taht configruation is simple. Your business logic can store proceeded data into db. It's almost the same solutions that consol app – Marcin Feb 23 '16 at 12:22
  • If you want to create consol app you can use quartz in it, your long business logic can run as quartz job and configuration of quartz like I describe in previous comment db or file. You can create common class for quartz configuration set and store(serialize) from MVC and deserialize inside consol app. – Marcin Feb 23 '16 at 12:24
  • @Marcin so i can create a console application, add the scheduler inside it (seems both quartz and hangfire have the ability to work with console app). and for the schedule setting , i can modify the configuration for the quartz from my asp.net MVC... this should work.. now i have find this approach which will be hybrid. 1) i will create the console application 2) inside my asp.net MVC action method , i will define the action method to call the console app using Process.Start("ConsoleApp.exe"). and this this case my scheduler will be calling the action method.... – John John Feb 23 '16 at 15:45
  • @Marcin the benefits of this approach is that admin will have the ability to access the hangfire or the quartz dashboard from the web.. while having quartz or hangfire runs inside the console app ,will not give us the ability to have a web based dashboard... – John John Feb 23 '16 at 15:46
  • @john G not necessarily but your solution is the simplest one and I like simple solutinos. I think you have recipe: 1. long busiiness logic outside IIS as consol app; 2. Scheduled by quartz.net or hangfire 3. Schedulemanaged by web – Marcin Feb 24 '16 at 07:55
  • @john G I'm just thinking, it's possible to run console app if you are not logged on this server? If nobody are logged? I think you must consider windows local service one more time, check some topics: http://stackoverflow.com/a/1000050/3139083 http://www.vbdotnetforums.com/windows-services/42775-advantages-disadvantages-windows-services.html# Because debuging of local service is troublesome you can create it as console app and then: http://stackoverflow.com/a/7764451/3139083 – Marcin Feb 24 '16 at 08:07
  • @Marcin i suppose that hangfire or quartz should be able to run console application , even if no users are logged in .. – John John Feb 24 '16 at 15:48

2 Answers2

1

In my opinion, if it is possible to solve the scheduling problem on the web application side, there is no need to create a scheduler task or a new console application for triggering purposes. The problem you will probably face when using scheduling task in a web application is generally common as you might see is that: The scheduler works like a charm during debugging of the web application, but not being able to trigger after publishing it to IIS. At this point the problem is generally related to IIS rather than the schedulers Quartz.NET, Hangfire, etc. Although there are lots of articles or solution methods posted on the web, unfortunately only some of them is working properly. In addition to this, most of them require lots of configuration settings on the web and machine configuration.

However, there are also some kind of solutions for such a kind of scheduling problem and I believe in that it is worthy to give a try Keep Alive Service For IIS 6.0/7.5. Just install it on the server to which you publish your application and enjoy. Then your published application will be alive after application pool recycling, IIS/Application restarting, etc. That is also used in our MVC application in order to send notification mails weekly and has been worked for months without any problem. Here are the sample code that I use in our MVC application. For more information please visit Scheduled Tasks In ASP.NET With Quartz.Net and Quartz.NET CronTrigger.


*Global.asax:*
protected void Application_Start()
{
    JobScheduler.Start();
}

*EmailJob.cs:*
using Quartz;

public class EmailJob : IJob
{
    public void Execute(IJobExecutionContext context)
    {
        SendEmail();
    }
}

*JobScheduler.cs:*
using Quartz;
using Quartz.Impl;

public class JobScheduler
{
    public static void Start()
    {
        IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
        scheduler.Start();

        IJobDetail job = JobBuilder.Create<EmailJob>().Build();
        ITrigger trigger = TriggerBuilder.Create()
            .WithIdentity("trigger1", "group1")
            .StartNow()
            .WithSchedule(CronScheduleBuilder
                .WeeklyOnDayAndHourAndMinute(DayOfWeek.Monday, 10, 00)
                //.WithMisfireHandlingInstructionDoNothing() //Do not fire if the firing is missed
                .WithMisfireHandlingInstructionFireAndProceed() //MISFIRE_INSTRUCTION_FIRE_NOW
                .InTimeZone(TimeZoneInfo.FindSystemTimeZoneById("GTB Standard Time")) //(GMT+02:00)
                )
            .Build();
        scheduler.ScheduleJob(job, trigger);
    }
} 
Murat Yıldız
  • 11,299
  • 6
  • 63
  • 63
  • John G want to separate this operation to console app because it's long time business opeation not because some problems with scheduling from web – Marcin Feb 26 '16 at 07:05
  • @Marcin I just wanted to deal with "... Vs .net scheduler tools with asp.net mvc to execute long running processes inside my asp.net MVC" part of his question... – Murat Yıldız Feb 26 '16 at 19:29
0
  • Also I create a View inside my asp.net mvc which allow users to set the hangfire schedule settings (this require to do an IIS reset on the host server for hangfire to get the new settings).

You're resetting your webserver to update a task's schedule? That doesn't sound healthy. What you might do is keep track of what the scheduled time should be, and on execution, check if the current time is within a certain range of the scheduled time (or has already been executed), otherwise abort the job.

The only thing I noted is that if I set the schedule to run on non-business hours (where no activity is made on IIS) then hangfire will not be able to call the job, and once the first request is made the missed jobs will run. I overcome this limitation by defining a windows task which calls IIS each 15 minutes, to keep application pool live, and it worked well...

Hangfire's documentation has a page about running delayed tasks that mentions what you need to change to accomodate this.

Using Windows' Task Scheduler doesn't seem like a good idea; it's not meant for the execution of ad-hoc, short-lived tasks. You probably need elevation to create tasks, and you'd probably need to define another scheduled task to clean up the mountain of tasks that would exist after a few dozen background jobs have been executed.

You're also correct that using Windows' Task Scheduler would make it more difficult to move your application around.

ErikHeemskerk
  • 1,623
  • 14
  • 30
  • ,, not sure i get your reply correctly .... so which approach you are sugesting to run long running backgorund tasks .. also you mentioned "Using Windows' Task Scheduler doesn't seem like a good idea..." can yuo adivce why ? – John John Feb 22 '16 at 13:07
  • I'm saying my advice would be to use Hangfire, as it's created to solve the exact problem you're having (background jobs). I've updated my answer to show the reasons why Windows Task Scheduler is probably _not_ a good idea. – ErikHeemskerk Feb 22 '16 at 13:10
  • so you are not against running long running and background process under IIS ? as hangfire (which i am using in my pilot project) will be deployed under iis ? second question, and what about the way i am keeping my applications pools alive , where i defined a simple windows task scheduler which runs every 15 minutes which calls the application ,, so in this way i am keeping my application pool alive... – John John Feb 22 '16 at 13:26
  • Like I said, Hangfire seems to be created to do the exact thing you want. Your way of keeping the application alive works, but a more efficient way would be to just tell IIS not to recycle your application. – ErikHeemskerk Feb 22 '16 at 13:34
  • now i conflict i am in, which lead me to create this question,, is that many articles mentioned that we should not run long running processing under iis,, as iis is designed to handle short requests ,,, while long running processes better as console applications,,, which are scheduled under windows task scheduler,,, – John John Feb 22 '16 at 13:37
  • That is indeed another question; my point was simply that *if* you want to do background tasks in IIS, you should use Hangfire (or something similar). Whether you *should* is another question entirely. If you ask me, tasks that take up to 40 minutes to execute should be running in console apps started by a Windows Service running Quartz. – ErikHeemskerk Feb 22 '16 at 13:41
  • why it is a different question,, actually this is what i am asking about ... using asp.net mvc Vs using console app to run background scheduled jobs.. – John John Feb 22 '16 at 13:43
  • I read your question as 'Hangfire/Quartz from IIS or Windows Task Scheduler', in which case my answer is the former. – ErikHeemskerk Feb 22 '16 at 13:51
  • so from my understanding is that you are against use Windows Task Scheduler ? but you are fine if i schedule the background tasks using quartz and implement these tasks as console applications ?? – John John Feb 22 '16 at 14:19
  • Yes, that would be my recommendation. – ErikHeemskerk Feb 22 '16 at 14:30
  • so if i want to implement a long running operation such as the network scanning process, then the best and more robust approach is to have this implemented as a console application,, then use quartz to schedule its execution ?? is this correct , in this way i will be decoupling the long running operation from iis and from asp.net mvc web application ?? – John John Feb 22 '16 at 15:37
  • "Best" is a malleable concept; you could also just implement a service using Quartz and perform the scan inside of that service. The pros and cons of that solution are outside of the scope of this question, I think. – ErikHeemskerk Feb 22 '16 at 16:10