使用CurrentRoleInstance.Id仅在一个实例中运行任务

时间:2012-03-15 07:29:37

标签: azure

在您在多个实例上部署Web角色并且需要安排应该仅由一个实例完成的任务的上下文中(例如,向具有某些统计信息的站点管理员发送电子邮件),使用它的可靠性如何RoleEnvironment.CurrentRoleInstance.Id为了使任务仅在一个实例上运行(例如,如果Id以IN_0完成,则只运行它)? 如果有人这样做过,我会对他的反馈感兴趣。

3 个答案:

答案 0 :(得分:10)

我不会使用实例ID。如果实例0重新启动(每月至少发生一次)会发生什么?现在您的调度程序或任务运行程序已脱机。

另一种解决方案是使用一种跨越实例的互斥锁。我想到的是一个blob租约。您实际上可以获取Blob上的租约以进行写入(并且只能有一个租赁持有者)。您可以在运行任务之前尝试获取blob租约。如果你得到它,运行任务。如果不这样做,请不要运行它。

略有变化:在一个线程中(假设从你的Run()方法开始),尝试获取租约,如果成功,则启动一个调度程序任务(可能是一个线程或其他东西)。如果您无法获得租约,请睡一分钟再试一次。最终,带有租约的实例将重新启动(或者由于某些其他原因它将消失)。几秒钟后,另一个实例将获取废弃的租约并启动新的调度程序任务。

史蒂夫马克思用租约写了关于并发的blog post。 Tyler Doerksen也有约good post个租约。

答案 1 :(得分:6)

是的,如果需要,可以使用InstanceId

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

它将是以下形式

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

像这样

访问批处理文件中的environmet变量
 %InstanceId%

然后您可以使用_的子字符串或最后一个索引从InstanceId获取索引。 如果具有索引0的此实例即使在重新启动后也将具有相同的索引。

更多细节 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

答案 2 :(得分:0)

如果您有多个实例,可以让一些执行代码块只运行一次,例如检查您正在执行的当前角色实例的ID。

您可以使用其他解决方案获得相同的结果,但这些可能需要更多工作,例如将任务与实例分离