Navigation

Monday 17 August 2009

SharePoint Timer Jobs and Multiple Servers

Timer jobs are wonderfully robust creatures. They effectively replace the "Windows Scheduled Task" for SharePoint servers, allowing you to run .Net code on a scheduled or "one off" basis.

However, there can be some confusion about running Timer Jobs on multiple servers, so this should clear it up a bit.

  1. By default Timer Jobs will only execute on the server that they are called from (typically the Central Administration server)
  2. Through code you can specify a specific box (SPServer) to run your Timer Job on.
  3. It is possible to run a Timer Job on every server on the farm (although this can be dangerous!)

The crux of all this is based on the SPJobDefinition constructor (http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.spjobdefinition.spjobdefinition.aspx).

The constructor includes a parameter for an SPServer object, which allows you to specify which server the timer job will run on.

Example Code 1 – Add Job to single Server:

The code below is for a Web Application scoped which will register a job definition on a single server. As Web Application scoped features are activated from Central Administration, it will use the current SPServer (i.e. the Central Admin server).

This is useful for code which modified content in the database, as you only want it to execute a single time.

public override void FeatureActivated(SPFeatureReceiverProperties properties)

{

SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;

SPJobDefinition job = new SPJobDefinition("CustomJobDef", webApp);

}

Example Code 2 – Add Job to All Servers:

The code below is for a Web Application scoped which will register a job definition on all web front end servers in the farm.

This is useful for code which modifies files or server settings, as you need it to execute separately for each server.

public override void FeatureActivated(SPFeatureReceiverProperties properties)

{

SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;

foreach (SPServer server in SPFarm.Local.Servers)

{

if (server.Role == SPServerRole.WebFrontEnd)

{

SPJobDefinition job = new SPJobDefinition("CustomJobDef", webApp, server, SPJobLockType.None);

}

}

}

Hope this helps! Enjoy!



4 comments:

  1. What if you specified all the WFE's to run that timer job, but specified passed SPJobLockType.Job instead of "None"? Would it still run on all WFEs?

    ReplyDelete
  2. Hi there!!

    Pretty good article!!! It clear me up some doubts, although it remains one.

    You said "The crux of all this is based on the SPJobDefinition constructor" but then you show code of SPFeatureReceiver where we create a new instance for the timer job.

    I've done a lot of timer jobs and I use an similar code of the SPFeatureReceiver as you show on example code 1, but never code anything in the constructors of SPJobDefinition except giving the name to the title (this.Title = JOB_NAME;).

    Should I code something else to guarantee that the timer job only runs on one server despite the windows service (OWSTIMER.EXE - Windows Sharepoint Services Timer) is running in all servers?

    Thanks in advance,

    André Pedroso

    ReplyDelete
  3. André

    Sorry, I perhaps should have been more specific.

    Basically the default SPJobDefinition constructor allows you to specify which server you want the code to run on.

    If you don't specify this then it will only run on a SINGLE SERVER (whichever server it is called from).

    In the case of a Web Application Feature this would be executed on the Central Administration server.

    It might be useful if you want to run code on EACH server in the farm (say .. to make file-system changes for IIS) to loop through each server and execute the same job on each one.

    Hope this clears it up :)

    ReplyDelete
  4. I could not find much information on MSDN about where a custom Timer job will run if there are multiple Web Front-end servers in farm. This article helped me. Good One!

    ReplyDelete

This blog has been moved to www.martinhatch.com

Note: only a member of this blog may post a comment.