我正在向未充分利用的Azure Web角色添加一个简单的工作进程。为了可靠性/正常运行时间,我在2个实例上运行此Web角色。在执行操作然后再次睡眠之前,将此工作进程设置为休眠约5分钟。通过将此工作进程添加到Web角色,它将在多个实例上运行,并且它们都将尝试同时执行相同的操作。通常使用队列可以克服这个问题,但我不需要任何精心设计的东西。我只是为了防止2个实例完全同步。
我的想法是将thread.sleep从硬编码等待时间更改为随机等待时间,如下所示:
Public Overrides Sub Run()
Trace.WriteLine("Worker Role entry point called.", "Information")
While (True)
Dim r As New Random
Dim wait As Integer = r.Next(60000, 600000)
Dim Minutes As Decimal = wait / 60000
Thread.Sleep(wait)
Trace.WriteLine(String.Format("Worker Role - Triggered on {0:f}. Waited {1:N2} Minutes.", Now(), Minutes), "Information")
End While
End Sub
实例0的输出:
信息:称为辅助角色入口点。
信息:工人角色 - 于2012年8月27日星期一上午9:37触发。等了7.71分钟
信息:工人角色 - 于2012年8月27日星期一上午9:41触发。等了4.25分钟
信息:工人角色 - 于2012年8月27日星期一上午9:49触发。等了7.87分钟
信息:工人角色 - 于2012年8月27日星期一上午9:53触发。等了4.77分钟
信息:工人角色 - 于2012年8月27日星期一上午10:03触发。等了9.91分钟。
实例1的输出:
信息:称为辅助角色入口点。
信息:工人角色 - 于2012年8月27日星期一上午9:38触发。等了9.47分钟
信息:工人角色 - 于2012年8月27日星期一上午9:44触发。等了6.15分钟
信息:工人角色 - 于2012年8月27日星期一上午9:48触发。等了3.41分钟
信息:工人角色 - 于2012年8月27日星期一上午9:49触发。等了1.63分钟
信息:工人角色 - 于2012年8月27日星期一上午9:58触发。等了8.26分钟
信息:工人角色 - 于2012年8月27日星期一上午10:01触发。等了3.14分钟。
这个计划是否有我没有看到的缺陷?感谢您的投入!
答案 0 :(得分:4)
嗯,要回答你的名义问题,这并不能保证他们两个人同时做某事。但它肯定会减少这种可能性。
也就是说,使用实际的并发控制机制并不一定要“精心设计”。来自http://blog.smarx.com/posts/simple-scheduling-in-windows-azure:
AutoRenewLease.DoEvery(blob, TimeSpan.FromMinutes(5), () => {
Trace.WriteLine("Doing stuff at {0:R}", DateTimeOffset.UtcNow);
});
为什么不这样做呢?它可以作为NuGet包使用,它可以缩短您的代码。 : - )
答案 1 :(得分:1)
这是您在拥有多个辅助角色实例时可能遇到的典型问题。解决方案很简单,使用Steve Marx的WazStorageExtensions库。该库允许您编写如下代码:
using (var arl = new AutoRenewLease(leaseBlob))
{
if (arl.HasLease)
{
// inside here, this instance has exclusive access
}
} // lease is released here
从示例中可以看出,如果某个实例有租约,则可以独占访问您正在执行的操作。
库使用blob租约,你可以将它与C#中的lock关键字进行比较。但是锁定blob允许您锁定不同的进程甚至不同的实例。当时只有一个实例可以租用blob,这意味着您可以确保进程不会在多个实例上同时运行。而且您仍然可以使用随机计时器来保持进程运行,而不必担心并发。