此代码是否可以使两个单独的Azure工作者实例同时执行操作?

时间:2023-01-18 18:36:36

I am adding a simple worker process to an underutilized Azure web role. I have this web role running on 2 instances for reliability/uptime. This worker process was to be set to sleep for around 5 min before performing an action and then sleeping again. By adding this worker process to the web role it will be running on multiple instances and they will both try to perform the same action at the same time. Normally this problem is overcome by using a queue but I don't need anything nearly that elaborate. I just something to keep the 2 instances from being completely syncronized.

我正在向未充分利用的Azure Web角色添加一个简单的工作进程。为了可靠性/正常运行时间,我在2个实例上运行此Web角色。在执行操作然后再次睡眠之前,此工作进程将设置为休眠约5分钟。通过将此工作进程添加到Web角色,它将在多个实例上运行,并且它们都将尝试同时执行相同的操作。通常使用队列可以克服这个问题,但我不需要任何精心设计的东西。我只是为了防止2个实例完全同步。

The idea I had was to change the thread.sleep from a hard coded wait time to a random wait time as follows:

我的想法是将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

Output from Instance 0:
Information: Worker Role entry point called.
Information: Worker Role - Triggered on Monday, August 27, 2012 9:37 AM. Waited 7.71 Minutes.
Information: Worker Role - Triggered on Monday, August 27, 2012 9:41 AM. Waited 4.25 Minutes.
Information: Worker Role - Triggered on Monday, August 27, 2012 9:49 AM. Waited 7.87 Minutes.
Information: Worker Role - Triggered on Monday, August 27, 2012 9:53 AM. Waited 4.77 Minutes.
Information: Worker Role - Triggered on Monday, August 27, 2012 10:03 AM. Waited 9.91 Minutes.

实例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分钟。

Output from Instance 1:
Information: Worker Role entry point called.
Information: Worker Role - Triggered on Monday, August 27, 2012 9:38 AM. Waited 9.47 Minutes.
Information: Worker Role - Triggered on Monday, August 27, 2012 9:44 AM. Waited 6.15 Minutes.
Information: Worker Role - Triggered on Monday, August 27, 2012 9:48 AM. Waited 3.41 Minutes.
Information: Worker Role - Triggered on Monday, August 27, 2012 9:49 AM. Waited 1.63 Minutes.
Information: Worker Role - Triggered on Monday, August 27, 2012 9:58 AM. Waited 8.26 Minutes.
Information: Worker Role - Triggered on Monday, August 27, 2012 10:01 AM. Waited 3.14 Minutes.

实例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分钟。

Does this plan have flaws that I'm not seeing? Thanks for your input!

这个计划是否有我没有看到的缺陷?感谢您的输入!

2 个解决方案

#1


4  

Well, to answer your titular question, this does nothing to guarantee both of them from doing something at the same time. But it would certainly make that less likely.

好吧,为了回答你的名义问题,这并不能保证他们两个人同时做某事。但它肯定会减少这种可能性。

That said, using an actual concurrency control mechanism doesn't have to be "elaborate." From http://blog.smarx.com/posts/simple-scheduling-in-windows-azure:

也就是说,使用实际的并发控制机制并不一定要“精心设计”。来自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);
});

Why not just do that? It's available as a NuGet package, and it shortens your code. :-)

为什么不这样做呢?它可以作为NuGet包使用,它可以缩短您的代码。 :-)

#2


1  

This is a typical issue you might be facing when having multiple instances of a worker role. And the solution is very simple, use Steve Marx's WazStorageExtensions library. That library allows you to write code like this:

这是具有多个辅助角色实例时可能遇到的典型问题。解决方案非常简单,使用Steve Marx的WazStorageExtensions库。该库允许您编写如下代码:

using (var arl = new AutoRenewLease(leaseBlob))
{
    if (arl.HasLease)
    {
        // inside here, this instance has exclusive access
    }
} // lease is released here

As you can see from the sample, a specific instance has exclusive access to whatever you're doing if it has a lease.

从示例中可以看出,如果某个实例有租约,则可以独占访问您正在执行的任何操作。

The library uses blob leases and you can compare this to the lock keyword in C#. But locking blobs allows you to have a lock over different processes and even different instances. Only one instances at the time can have a lease on a blob, meaning you can be sure that a process doesn't run simultaneously over multiple instances. And you can still use your random timer to keep the process running, without having to worry about concurrency.

该库使用blob租约,您可以将其与C#中的lock关键字进行比较。但是锁定blob允许您锁定不同的进程甚至不同的实例。当时只有一个实例可以在blob上进行租约,这意味着您可以确保进程不会在多个实例上同时运行。您仍然可以使用随机计时器来保持进程运行,而不必担心并发。

#1


4  

Well, to answer your titular question, this does nothing to guarantee both of them from doing something at the same time. But it would certainly make that less likely.

好吧,为了回答你的名义问题,这并不能保证他们两个人同时做某事。但它肯定会减少这种可能性。

That said, using an actual concurrency control mechanism doesn't have to be "elaborate." From http://blog.smarx.com/posts/simple-scheduling-in-windows-azure:

也就是说,使用实际的并发控制机制并不一定要“精心设计”。来自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);
});

Why not just do that? It's available as a NuGet package, and it shortens your code. :-)

为什么不这样做呢?它可以作为NuGet包使用,它可以缩短您的代码。 :-)

#2


1  

This is a typical issue you might be facing when having multiple instances of a worker role. And the solution is very simple, use Steve Marx's WazStorageExtensions library. That library allows you to write code like this:

这是具有多个辅助角色实例时可能遇到的典型问题。解决方案非常简单,使用Steve Marx的WazStorageExtensions库。该库允许您编写如下代码:

using (var arl = new AutoRenewLease(leaseBlob))
{
    if (arl.HasLease)
    {
        // inside here, this instance has exclusive access
    }
} // lease is released here

As you can see from the sample, a specific instance has exclusive access to whatever you're doing if it has a lease.

从示例中可以看出,如果某个实例有租约,则可以独占访问您正在执行的任何操作。

The library uses blob leases and you can compare this to the lock keyword in C#. But locking blobs allows you to have a lock over different processes and even different instances. Only one instances at the time can have a lease on a blob, meaning you can be sure that a process doesn't run simultaneously over multiple instances. And you can still use your random timer to keep the process running, without having to worry about concurrency.

该库使用blob租约,您可以将其与C#中的lock关键字进行比较。但是锁定blob允许您锁定不同的进程甚至不同的实例。当时只有一个实例可以在blob上进行租约,这意味着您可以确保进程不会在多个实例上同时运行。您仍然可以使用随机计时器来保持进程运行,而不必担心并发。