Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using CurrentRoleInstance.Id to run a task in just one instance

Tags:

azure

In a context where you are deploying a web role over multiple instances and require to schedule a task that should be done by one instance only (like sending an email to the site admin with some stats), how reliable is it to use RoleEnvironment.CurrentRoleInstance.Id in order to make the task run on one instance only (like only running it if the Id finishes with IN_0) ? If anyone has ever done this, I'd be interested in his feedback.

like image 761
ThomasWeiss Avatar asked Mar 15 '12 07:03

ThomasWeiss


2 Answers

I wouldn't use instance ID. What happens if instance 0 gets rebooted (which happens at least once per month)? Now your scheduler or task-runner is offline.

An alternate solution is to use a type of mutex that spans instances. The one I'm thinking of is a blob lease. You can actually acquire a lease on a blob for writing (and there can only be one lease-holder). You could attempt to get a blob lease before running a task. If you get it, run task. If you don't, don't run it.

A slight variation: In a thread (let's say started from your Run() method), attempt to acquire a lease and if successful, launch a scheduler task (maybe a thread or something). If you cannot acquire the lease, sleep for a minute and try again. Eventually, the instance with the lease will be rebooted (or it'll disappear for some other reason). After a few seconds, another instance will acquire the abandoned lease and start up a new scheduler task.

Steve Marx wrote a blog post about concurrency using leases. Tyler Doerksen also has a good post about leases.

like image 143
David Makogon Avatar answered Nov 18 '22 21:11

David Makogon


yes you can use the InstanceId if needed specificaly

 <Startup>
  <Task commandLine="StartUpTasks\WindowService\InstallWindowService.bat"  executionContext="elevated" taskType="background" >
  <Environment>
    <Variable name="InstanceId">
        <RoleInstanceValue xpath="/RoleEnvironment/CurrentInstance/@id"/>
    </Variable>
   </Environment>
  </Task>
 </Startup>

it will be of following form

<deployment Id>.<Application Name>.<Role Name>_IN_<index>
 Example mostly MyRole_IN_0, MyRole_IN_1

Access the environmet variable in batch file like this

 %InstanceId%

You cane then use substring or last index of _ to get the index from InstanceId. if this instance having index 0 will have the same index even after a reboot.

More Details http://blogs.msdn.com/b/cclayton/archive/2012/05/17/windows-azure-start-up-tasks-part-2.aspx

http://msdn.microsoft.com/en-us/library/windowsazure/hh404006.aspx

like image 6
sudhAnsu63 Avatar answered Nov 18 '22 21:11

sudhAnsu63