メッセージ中継点
プロデューサは、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 に設定されている場合、メッセージが失われ、これは良い状況ではありません。バックアップ スイッチを使用すると、破棄されるメッセージを保存し、必要なときにこれらのメッセージを取得できます。実際、バックアップ スイッチには特別なことは何もなく、メイン スイッチと同じであり、バックアップとしてのみ機能します。
プロデューサーコード
-
マスタースイッチを作成する場合、パラメータ引数を与え、マスタースイッチのバックアップスイッチを設定し、バックアップスイッチの名前を指定します。
-
次に、バックアップ交換を宣言し、破棄されたメッセージを保存するキューをバインドします。
-
メッセージの送信時に、必須パラメータは 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);
このように、異常な状況が発生した場合 (サービスの再起動後など)、メッセージは残ります。
注: メッセージの永続性はパフォーマンスに影響を与えますが、信頼性とスループットのバランスをとるために貴重なメッセージの永続性を確保するだけです。