.Net Core&RabbitMQ メッセージ ストレージの信頼性の高いメカニズム

メッセージ中継点

プロデューサは、RabbitMQ にメッセージを送信します。スイッチが自身のタイプと RoutingKey に従ってキューと一致する場合、メッセージは関連するキューに保存されます。メッセージのプロデューサの設定に応じて、メッセージが失われるか、プロデューサに送り返されます。

  • プロデューサが Mandatory を設定し、それが true の場合、メッセージはプロデューサに返されます。

  • メッセージの損失を避けるために、プロデューサが Mandatory または false を設定すると、スイッチをストレージを担当するバックアップ スイッチにルーティングできます。

必須

プロデューサがメッセージを送信するとき、メッセージが RabbitMQ に到着した後にスイッチが自身のタイプと RoutingKey に従って適切なキューを見つけられない場合に、メッセージの方向を決定するために必須のパラメータを設定できます。

  • 必須が true の場合、メッセージはプロデューサーに返されます。

  • 必須が false の場合、メッセージは破棄されます。

 プロデューサーコード

BasicPublish メソッドのパラメーターで Required を true に設定し、キューがまだ宣言されていない場合、スイッチは 1 つだけあり、メッセージが返されます。

var connFactory = new ConnectionFactory
{
    HostName = "xxx.xxx.xxx.xxx",
    Port = 5672,
    UserName = "rabbitmqdemo",
    Password = "rabbitmqdemo@test",
    VirtualHost = "rabbitmqdemo"};
using (var conn = connFactory.CreateConnection())
{
    using (var channel = conn.CreateModel())
    {
        var exchangeName = "mandatory_publishsubscribe_exchange";
        channel.ExchangeDeclare(exchange: exchangeName, type: "fanout");
        while (true)
        {
            Console.WriteLine("消息内容(exit退出):");
            var message = Console.ReadLine();
            if (message.Trim().ToLower() == "exit")
            {
                break;
            }

            var body = Encoding.UTF8.GetBytes(message);
            channel.BasicPublish(exchange: exchangeName, routingKey: "", mandatory: true, basicProperties: null, body: body);
            Console.WriteLine("消息内容发送完毕:" + message);
        }
    }
}

プロデューサがメッセージを送信し、エクスチェンジがメッセージを受信しますが、対応するキューが存在しないため、メッセージが返されます。

 メッセージがプロデューサーに返されたことを直感的に知るために、返されたメッセージを監視するリスナーを追加できます。

フォールバックメッセージをリッスンする

必須が true に設定されている場合、メッセージがロールバックされるときにメッセージを聞くことができます

channel.BasicReturn += new EventHandler<RabbitMQ.Client.Events.BasicReturnEventArgs>((sender, e) =>
{
    var message = Encoding.UTF8.GetString(e.Body.ToArray());
    Console.WriteLine($"收到回退消息:{message}");
});

一致するキューがないため、プロデューサーはメッセージを送信し、メッセージが返されます。返されたメッセージは直感的に確認できます。

 

 バックアップスイッチ

必須が false に設定されている場合、メッセージが失われ、これは良い状況ではありません。バックアップ スイッチを使用すると、破棄されるメッセージを保存し、必要なときにこれらのメッセージを取得できます。実際、バックアップ スイッチには特別なことは何もなく、メイン スイッチと同じであり、バックアップとしてのみ機能します。

 プロデューサーコード

  1. マスタースイッチを作成する場合、パラメータ引数を与え、マスタースイッチのバックアップスイッチを設定し、バックアップスイッチの名前を指定します。

  2. 次に、バックアップ交換を宣言し、破棄されたメッセージを保存するキューをバインドします。

  3. メッセージの送信時に、必須パラメータは false に設定されます。

var connFactory = new ConnectionFactory
{
    HostName = "xxx.xxx.xxx.xxx",
    Port = 5672,
    UserName = "rabbitmqdemo",
    Password = "rabbitmqdemo@test",
    VirtualHost = "rabbitmqdemo"};
using (var conn = connFactory.CreateConnection())
{
    using (var channel = conn.CreateModel())
    {
        var exchangeName = "aedemo_publishsubscribe_exchange";
        var alternateExchangeName = "aedemo_ae_publishsubscribe_exchange";
        var arguments = new Dictionary<string, object>
        {
            { "alternate-exchange", alternateExchangeName }
        };
        channel.ExchangeDeclare(exchange: exchangeName, type: "fanout", arguments: arguments);
        channel.ExchangeDeclare(exchange: alternateExchangeName, type: "fanout");

        var alternateExchangeQueueName = alternateExchangeName + "_worker";
        channel.QueueDeclare(queue: alternateExchangeQueueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
        channel.QueueBind(queue: alternateExchangeQueueName, exchange: alternateExchangeName, routingKey: "");

        while (true)
        {
            Console.WriteLine("消息内容(exit退出):");
            var message = Console.ReadLine();
            if (message.Trim().ToLower() == "exit")
            {
                break;
            }

            var body = Encoding.UTF8.GetBytes(message);
            channel.BasicPublish(exchange: exchangeName, routingKey: "", mandatory: false, basicProperties: null, body: body);
            Console.WriteLine("消息内容发送完毕:" + message);
        }
    }
}

プログラムを起動すると、Web パネルからマスタースイッチとバックアップスイッチの両方が作成され、マスタースイッチには AE マークが付いていることがわかります。

プロデューサはメッセージを送信します。メイン スイッチによって照合された後、適切なキューがない場合、そのメッセージはバックアップ スイッチに転送され、そのキューにルーティングされて保存されます。

 注: ファンアウト スイッチを使用することをお勧めします。ダイレクトなどの他のスイッチの場合、マスター スイッチがバックアップ スイッチに転送するとき、マッチング時に、メッセージの指定された RoutingKey が対応するキューと一致しない場合、メッセージは失われます。 . このように、当初の予想は外れてしまいます。

持久化

RabbitMQ がシステムのダウンタイム、再起動、シャットダウンなどの異常な状態にある場合、データ損失が発生し、信頼性が低下する可能性があります。この状況に対応して、RabbitMQ はメッセージ自体とメタデータ (キュー、スイッチ、バインディング情報) をディスクに保存する永続化メカニズムを提供します。具体的には3種類の永続性に分けられます

  • スイッチの永続性

  • キューの永続性

  • メッセージの永続性

スイッチの永続性

RabbitMQ が異常な状況 (サービスの再起動など) に遭遇したとき、スイッチの永続性が設定されていないと、スイッチに関連するデータが失われ、指定されたスイッチにメッセージを送信する際にプロデューサーが失敗します。

サービス再起動例外

1. Web で新しいスイッチを作成し、非永続モードを指定します。

 2. 新しいキューを作成し、非永続モードを指定します。

 3. スイッチとキュー間のバインド関係を設​​定します。

 4. プロデューサの前部は正常にメッセージを送信しますが、途中でサービスが再起動されると、スイッチ、キュー、バインディング関係がすべてクリアされ、プロデューサはメッセージの送信を続行し、例外が発生します。

  

永続化設定

スイッチを宣言するときに、持続性パラメーターを true に設定するように指定できます (Web パネルで設定することもできます)。

channel.ExchangeDeclare(exchange: exchangeName, type: "fanout", durable: true, arguments: null);

RabbitMQ サービスが再起動され、プロデューサーはスイッチへのメッセージの送信を続けます。

 

キューの永続性

キューの永続性は、キューの宣言時に持続性パラメーターを true に設定することです。キューが持続性ではない場合、異常な状況 (サービスの再起動など) の後、キューのメタデータが失われ、メッセージが失われます。保存されているものも失われます。

サービス再起動例外

1. Web でスイッチを作成し、永続モードに設定します。

2. キューを作成し、非永続モードに設定します。

3. スイッチとキュー間のバインド関係を設​​定します。

4. プロデューサのフロント部分は通常どおりメッセージを送信します。サービスが途中で再起動された後、キューとバインド関係がクリアされ、プロダクションはメッセージの送信を続けます。一致するキューが失敗した場合、メッセージはプロデューサに返されます。

永続化設定

キューを宣言するときに、true に設定される持続性パラメータを指定できます (Web パネルでも設定できます)。

channel.QueueDeclare(queue: queueName, durable: true, exclusive: false, autoDelete: false, arguments: null);

RabbitMQ サービスが再起動され、プロデューサーはスイッチへのメッセージの送信を続けます。

メッセージの永続性

キューの永続性は、キュー自体のデータが失われないことのみを保証できますが、キューに格納されているメッセージが失われないことは保証できません。

永続化設定

異常な状況 (サービスの再起動など) によってメッセージ自体が失われないように、メッセージに永続性を設定する必要があります。メッセージを送信するときに、メッセージの永続性をサポートするためにメッセージの基本プロパティを設定できます。

var basicProperties = channel.CreateBasicProperties();
basicProperties.DeliveryMode = 2;// 1非持久化 2持久化
channel.BasicPublish(exchange: exchangeName, routingKey: "", mandatory: true, basicProperties: basicProperties, body: body);

このように、異常な状況が発生した場合 (サービスの再起動後など)、メッセージは残ります。

 注: メッセージの永続性はパフォーマンスに影響を与えますが、信頼性とスループットのバランスをとるために貴重なメッセージの永続性を確保するだけです。

おすすめ

転載: blog.csdn.net/qq_41872328/article/details/126785876
おすすめ