0

十分に活用されていない Azure Web ロールに単純なワーカー プロセスを追加しています。信頼性/稼働時間のために、この Web ロールを 2 つのインスタンスで実行しています。このワーカー プロセスは、アクションを実行する前に約 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 からの出力:
情報: Worker Role エントリ ポイントが呼び出されました。
情報: Worker ロール - 2012 年 8 月 27 日月曜日の午前 9 時 37 分にトリガーされます。7.71 分待ちました。
情報: Worker ロール - 2012 年 8 月 27 日月曜日の午前 9 時 41 分にトリガーされます。4.25 分待った。
情報: Worker ロール - 2012 年 8 月 27 日月曜日の午前 9 時 49 分にトリガーされます。7.87 分待ちました。
情報: Worker ロール - 2012 年 8 月 27 日月曜日の午前 9 時 53 分にトリガーされます。4.77 分待ちました。
情報: Worker ロール - 2012 年 8 月 27 日月曜日の午前 10:03 にトリガーされます。9.91 分待ちました。

インスタンス 1 からの出力:
情報: Worker Role エントリ ポイントが呼び出されました。
情報: Worker ロール - 2012 年 8 月 27 日月曜日の午前 9 時 38 分にトリガーされます。9.47分待ちました。
情報: Worker ロール - 2012 年 8 月 27 日月曜日の午前 9 時 44 分にトリガーされます。6.15 分待ちました。
情報: Worker ロール - 2012 年 8 月 27 日月曜日の午前 9 時 48 分にトリガーされます。3.41分待ちました。
情報: Worker ロール - 2012 年 8 月 27 日月曜日の午前 9 時 49 分にトリガーされます。1.63 分待ちました。
情報: Worker ロール - 2012 年 8 月 27 日月曜日の午前 9 時 58 分にトリガーされます。8.26分待ちました。
情報: Worker ロール - 2012 年 8 月 27 日月曜日の午前 10:01 にトリガーされます。3.14分待ちました。

この計画には、目に見えない欠陥がありますか? ご意見ありがとうございます。

4

2 に答える 2

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 パッケージとして入手でき、コードを短縮します。:-)

于 2012-08-27T20:55:00.777 に答える
1

これは、worker ロールのインスタンスが複数ある場合に直面する可能性がある典型的な問題です。解決策は非常に簡単で、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 キーワードと比較できます。ただし、ブロブをロックすると、さまざまなプロセスやさまざまなインスタンスをロックできます。一度に 1 つのインスタンスのみが BLOB のリースを持つことができます。つまり、プロセスが複数のインスタンスで同時に実行されないようにすることができます。また、並行性を気にすることなく、ランダム タイマーを使用してプロセスを実行し続けることができます。

于 2012-08-27T20:53:22.910 に答える