1. RabbitMQを使用する利点は何ですか?
1.デカップリング、システムAはコード内でシステムBとシステムCのコードを直接呼び出します。将来システムDが接続された場合、システムAはコードを変更する必要があり、面倒です。
2.非同期、メッセージキューへのメッセージの書き込み、非必須のビジネスロジックは非同期で実行され、応答速度が向上します。
3.ピークがカットされ、同時実行性が大きい場合、すべての要求がデータベースに直接送信され、データベース接続が異常になる
2. RabbitMQのブローカーは何ですか?クラスターとはどういう意味ですか?
ブローカーは1つ以上のerlangノードの論理グループを指し、RabbitMQアプリケーションはノードで実行されています。クラスターはブローカーに基づいており、ノード間でメタデータを共有するという制約を追加します。
3. RabbitMQの概念におけるチャネル、交換、キューは論理的な概念ですか、それともプロセスエンティティに対応していますか?彼らはどのような役割を果たしていますか?
キューには独自のerlangプロセスがあります。
Exchangeは、バインド関係を維持するためにルックアップテーブルとして内部的に実装されています。
チャネルは、ルーティング作業を実際に行うエンティティです。つまり、routing_keyに従ってメッセージをキューに配信します。
AMQPプロトコルの説明によると、チャネルは実際のTCP接続より上の仮想接続であり、すべてのAMQPコマンドはチャネルを通じて送信され、各チャネルには一意のIDがあります。
チャネルは単一のオペレーティングシステムスレッドでのみ使用できるため、特定のチャネルに配信されるメッセージは順序どおりです。
ただし、1つのオペレーティングシステムスレッドで複数のチャネルを使用できます。
4. vhostとは何ですか?それはどのような役割を果たしますか?
vhostは仮想ブローカー、つまりmini-RabbitMQサーバーとして理解できます。独立したキュー、交換、バインディングなどが含まれますが、最も重要なことは、vhostのスコープ内でユーザー制御を実現できる独立した権限システムがあることです。もちろん、RabbitMQのグローバルな観点から見ると、vhostはさまざまな権限を持つハンドとして使用できます。
セグメント(典型的な例は、異なるアプリケーションが異なる仮想ホストで実行できることです)。
5.メッセージはどの送信に基づいていますか?
TCP接続の作成と破棄のオーバーヘッドが大きく、同時実行の数はシステムリソースによって制限されるため、パフォーマンスのボトルネックが発生します。RabbitMQはチャネルを使用してデータを送信します。チャネルは、実際のTCP接続内で確立される仮想接続であり、各TCP接続のチャネル数に制限はありません。
6.メッセージはどのように配信されますか?
少なくとも1つのコンシューマがキューにサブスクライブしている場合、メッセージはラウンドロビン方式でコンシューマに送信されます。各メッセージは、サブスクライブしたコンシューマーにのみ配信されます(コンシューマーがメッセージを処理して通常どおり確認できる場合)。
7.メッセージのルーティング方法は?
概念的には、メッセージルーティングには、スイッチ、ルーティング、バインディングの3つの部分が必要です。プロデューサーはメッセージをスイッチにパブリッシュし、バインディングはメッセージがルーターから特定のキューにルーティングされる方法を決定します;メッセージは最終的にキューに到達し、コンシューマーによって受信されます。
メッセージがスイッチにパブリッシュされると、メッセージにはルーティングキーが含まれます。ルーティングキーは、メッセージの作成時に設定されます。
キューのルーティングキーを使用して、キューをスイッチにバインドできます。
メッセージがスイッチに到達すると、RabbitMQはメッセージのルーティングキーをキューのルーティングキーと照合します(スイッチごとに異なるルーティングルール)。
キューと一致する場合、メッセージは対応するキューに配信され、どのキューとも一致しない場合、メッセージは「ブラックホール」に入ります。
一般的に使用されるスイッチは、主に次の3つのタイプに分類されます。
直接:ルーティングキーが完全に一致する場合、メッセージは対応するキューに配信されます
ファンアウト:スイッチがメッセージを受信すると、バインドされたすべてのキューにブロードキャストされます
トピック:異なるソースからのメッセージが同じキューに到達できるようにすることができます。トピックスイッチを使用する場合、ワイルドカードを使用できます。たとえば、「*」は特定の位置にある任意のテキストに一致し、「。」はルーティングキーを部分に分割し、「#」はすべてのルールに一致します。特記事項:トピックスイッチに送信されるメッセージはランダムに設定できません(routing_key)、
「。」で区切られた一連の識別子でなければなりません。
8.メタデータとは何ですか?メタデータの種類は何ですか?何が含まれていますか?クラスターに関連するメタデータは何ですか?メタデータはどのように保存されますか?メタデータはどのようにクラスターに分散されますか?
非クラスターモードでは、メタデータは主にキューメタデータ(キュー名と属性など)、Exchangeメタデータ(交換名、タイプと属性など)、バインディングメタデータ(ルーティング関係を格納するためのルックアップテーブル)、Vhostメタデータに分けられます。名前空間の制約とvhostのスコープ内の最初の3つのセキュリティ属性設定)。
クラスタモード、さらにクラスタノード関係情報と位置情報でノードを含みます。メタデータは、アーランノードのタイプに応じて、RAMのみに保存されるか、RAMとディスクの両方に保存されるかを決定します。メタデータは、クラスター内のノード全体に分散されます。
9.単一ノードシステムと複数ノードで構成されるクラスタシステムでのキューの宣言、交換、およびバインディングの違いは何ですか?
A:単一のノードでキューを宣言すると、ノードの関連メタデータが変更されている限り、Queue.Declare-ok応答が返されます。クラスターでキューを宣言すると、クラスター上のすべてのノードがQueue.Declare-ok応答は、メタデータが正常に更新された後にのみ取得されます。また、ノードタイプが
RAMノードの場合、変更されたデータはメモリにのみ保存され、タイプがディスクノードの場合、ディスクに保存されたデータも変更する必要があります。
デッドレターキューおよびデッドレターエクスチェンジ:デッドレターエクスチェンジと呼ばれるDLX(Dead-Letter-Exchange)メッセージがデッドレターになるとき、メッセージが存在するキューがx-dead-letter-exchangeの場合パラメータ、それからx-dead-letter-exchangeに対応する取引所に送信されます。この交換はデッドレター交換と呼ばれます
Exchangeer、このデッドレター交換にバインドされたキューはデッドレターキューです。
10.メッセージがRabbitMQに正しく送信されるようにする方法を教えてください。
RabbitMQは送信者確認モードを使用して、メッセージがRabbitMQに正しく送信されるようにします。
送信者確認モード:チャネルを確認モード(送信者確認モード)に設定すると、チャネルに投稿されたすべてのメッセージに一意のIDが割り当てられます。メッセージが宛先キューに配信されると、またはメッセージがディスクに書き込まれた後(永続メッセージ)、チャネルは確認応答をメッセージ(メッセージの一意のIDを含む)に送信します。
RabbitMQで内部エラーが発生してメッセージが失われた場合、nack(確認されていない)メッセージが送信されます。送信者確認モードは非同期であり、プロデューサーアプリケーションは確認を待機しながらメッセージを送信し続けることができます。確認メッセージがプロデューサーアプリケーションに到達すると、プロデューサーアプリケーションのコールバックメソッドは
確認メッセージを処理するトリガー。
11.メッセージ受信者がメッセージを確実に消費するようにするにはどうすればよいですか?
受信者メッセージ確認メカニズム:コンシューマーは各メッセージを受信した後に確認する必要があります(メッセージ受信とメッセージ確認は2つの異なる操作です)。
コンシューマーがメッセージを確認した場合のみ、RabbitMQはメッセージをキューから安全に削除できます。ここではタイムアウトメカニズムは使用されず、RabbitMQはコンシューマの接続を中断することによってメッセージを再送信する必要があるかどうかを確認するだけです。つまり、接続が中断されない限り、RabbitMQはコンシューマにメッセージを処理するための十分な時間を与えます。
いくつかの特殊なケースを以下に示します。
コンシューマーがメッセージを受信し、切断するかサブスクライブを解除してから確認すると、RabbitMQはメッセージが配信されていないと見なし、次にサブスクライブしたコンシューマーに再配信します。(繰り返しメッセージを消費するという隠れた危険があり、bizIdに従って重複排除する必要がある場合があります)
コンシューマーがメッセージを受信してもメッセージを確認せず、接続が切断されていない場合、RabbitMQはコンシューマーがビジーであり、それ以上のメッセージをコンシューマーに配信しないと考えます。
12.メッセージの繰り返し配信または消費を回避する方法は?
メッセージの生成中、MQは、重複排除およびべき等性(メッセージ配信が失敗して再送信される)の基礎として、プロデューサーによって送信された各メッセージのinner-msg-idを内部的に生成し、重複したメッセージがキューに入らないようにします;メッセージが消費されるとき、メッセージ本文にbizIdが必要(支払いID、注文ID、投稿IDなど、同じビジネスでグローバルに一意)
重複排除とべき等性の基礎として、同じメッセージが繰り返し消費されることを回避します。
この質問は、ビジネスシナリオの次のポイントに回答します。
1.たとえば、データベースの挿入操作を行うには、このメッセージが表示されます。簡単です。このメッセージに一意の主キーを作成してください。繰り返し使用された場合でも、主キーの競合が発生し、データベース内のダーティデータが回避されます。
2.別の例として、このメッセージを受け取ってredis set操作を実行する場合、それは簡単で、解決する必要はありません。何回設定しても結果は同じであるため、set操作はもともとべき等であると見なされます。
3.上記の2つの状況が十分でない場合は、大きな動きに進みます。消費記録用のサードパーティメディアを準備します。redisを例にとると、メッセージにグローバルIDを割り当てます。メッセージが消費されたら、<id、message>をKVの形式でredisに書き込みます。消費者が消費を開始する前に、最初にredisに移動して、消費レコードがあるかどうかを確認します。
13.データ損失の問題を解決するにはどうすればよいですか?
1.プロデューサーがデータを失う
プロデューサーのメッセージがMQに配信されない場合はどうなりますか?データを失うプロデューサーの観点から、RabbitMQはプロデューサーがメッセージを失わないことを保証するためにトランザクションと確認モードを提供します。
トランザクションメカニズムは、メッセージを送信する前にトランザクションを開き(channel.txSelect())、メッセージを送信することを意味します。送信プロセス中に異常が発生した場合、トランザクションはロールバックされます(channel.txRollback())。 (channel.txCommit())。
ただし、デメリットはスループットが低下することです。したがって、ブロガーの経験によれば、確認モードの大部分は本番環境で使用されます。チャネルが確認モードに入ると、チャネルに投稿されたすべてのメッセージに一意のID(1から始まる)が割り当てられます。メッセージが一致するすべてのキューに配信されると、rabbitMQはにACKを送信します
プロデュースメッセージは、メーカーがrabiitMQがメッセージを処理できませんでした場合は、あなたにNACKメッセージを送信する送信先キューに到達知る権利を持っている、(ユニークIDがメッセージを含む)によって、あなたはリトライ動作を行うことができます。
2.メッセージキューがデータを失った
メッセージキュー内のデータの損失に対処するために、通常、永続ディスクの構成がオンになっています。この永続化構成は、確認メカニズムと組み合わせて使用できます。メッセージがディスクに永続化された後、Ack信号をプロデューサに送信できます。このようにして、メッセージがディスクに保持される前にrabbitMQが強制終了された場合、プロデューサーはAck信号を受信せず、プロデューサーは自動的に再送信します。
永続化する方法は、ここでちなみに、実際には非常に簡単です。次の2つのステップだけです。
①キューの永続識別子をtrueに設定します。これは、永続的なキューであることを意味します
②メッセージ送信時のDeliveryMode = 2
この設定後、rabbitMQがハングした場合でも、再起動後にデータを復元できます。メッセージがハードディスクに保持されない場合、サービスが停止している可能性があります。この場合、ミラーリングキューを導入することでミラーリングキューを導入できますが、メッセージが100%失われないという保証はありません(クラスター全体がハングアップします)。
3.消費者はデータを失う
手動確認モードを有効にすると、この問題を解決できます
①自動確認モードでは、コンシューマが電話を切り、確認メッセージがキューに戻ります。コンシューマーが例外をスローした場合、メッセージは正常に処理されるまで継続的に再送信されます。メッセージが失われることはありません。サービスがハングした場合でも、未処理のメッセージはキューに返されますが、例外により、メッセージは継続的に再試行されます。
②手動確認モード。コンシューマが処理前に死亡した場合、ackへの応答がないときにメッセージが他のコンシューマに繰り返し送信されます。リスナが例外を処理し、例外がキャプチャされなかった場合、メッセージは繰り返し受信されます。常に例外をスローします;例外がキャッチされたが最終的に確認されなかった場合、常に繰り返し送信されます
メッセージ(再試行メカニズム)。
③未確認モード、確認= "なし"は確認メカニズムを使用せず、メッセージが送信されるとすぐにキューから削除されます。クライアントが異常または切断されているかどうかに関係なく、送信後すぐに削除され、再送信されません。
14.デッドレターキューおよび遅延キューの使用
デッドレターニュース:
メッセージが拒否され(Basic.RejectまたはBasic.Nack)、requeueパラメータの値がfalseに設定されている
メッセージの期限が切れました
キューが最大長に達しました
期限切れのメッセージ:
メッセージの有効期限を設定するrabbitmqには2つのタイプがあります。1つ目はキューを設定することです。この設定の後、キュー内のすべてのメッセージは同じ有効期限になります。2つ目はメッセージ自体を設定することです、その場合、各メッセージの有効期限は異なります。これら2つの方法を同時に使用すると、有効期限が短くなります
数値が優先されます。メッセージが有効期限に達し、消費されていない場合、メッセージはデッドレターメッセージになります。
キュー設定:キューが宣言されたときにx-message-ttlパラメータを使用します(ミリ秒単位)。
単一メッセージ設定:メッセージ属性の有効期限パラメーターの値を設定します。単位はミリ秒です
遅延キュー:rabbitmqには遅延キューはありませんが、メッセージの有効期限と配信不能キューを設定することにより、遅延キューをシミュレートできます。コンシューマーは、メッセージが送信されるキューではなく、デッドレターエクスチェンジにバインドされたキューをリッスンします。
上記の基本的な知識により、次の要件を満たします。
要件:
ユーザーはシステムで注文を作成し、ユーザーが時間内に支払いを行わなかった場合、注文は自動的にキャンセルされます。
分析:
1.上記の状況では、遅延キューを使用して、遅延キューを作成する方法が適しています。
2.遅延キューは、期限切れのメッセージ+配信不能キューによって時間を計ることができます
3.期限切れのメッセージは、キューにx-message-ttlパラメータを設定することで実装されます
4.デッドレターキューは、キューが宣言されたときにx-dead-letter-exchangeパラメータをキューに設定してから、x-dead-letter-exchangeに対応するスイッチをバインドするキューを宣言します。
ConnectionFactoryファクトリ=新しいConnectionFactory(); factory.setHost( "127.0.0.1"); factory.setPort(AMQP.PROTOCOL.PORT); factory.setUsername( "guest"); factory.setPassword( "guest"); 接続connection = factory.newConnection(); チャネルチャネル= connection.createChannel(); // 1つの受信によって削除されたメッセージの 交換機と列文字列EXCHANGE_DEAD_NAME = "exchange.dead"; 文字列QUEUE_DEAD_NAME = "queue_dead"; channel.exchangeDeclare(EXCHANGE_DEAD_NAME、BuiltinExchangeType.DIRECT); channel.queueDeclare(QUEUE_DEAD_NAME、false、false、false、null); channel.queueBind(QUEUE_DEAD_NAME、EXCHANGE_DEAD_NAME、 "routingkey.dead"); 文字列EXCHANGE_NAME = "交換。 文字列QUEUE_NAME = " channel.exchangeDeclare(EXCHANGE_NAME、BuiltinExchangeType.FANOUT); Map <String、Object> arguments = new HashMap <String、Object>(); //キュー内のすべてのメッセージの有効期限 引数を均一に設定します。 put( "x-message-ttl"、30000); //コンシューマがキューにアクセスしない場合のミリ秒数を設定し、キュー時間の 引数を削除します。put( "x-expires"、20000); //最新のキューを設定しますN個のメッセージ、N個を超えるメッセージがある場合、前のメッセージはキューの 引数から削除されます.put( "x-max-length"、4); //キューのコンテンツの最大スペースを設定し、しきい値を超えた場合は削除します以前のメッセージ arguments.put( "x-max-length-bytes"、1024); //削除されたメッセージを指定されたスイッチ(通常はx-dead-letter-exchangeおよびx-dead-letter-routing-key )にプッシュします設定する必要が arguments.put(「X-デッド・レター・交流」、「exchange.dead」); //キーをルーティング対応する指定プッシュスイッチにメッセージを削除 arguments.put( "x-dead-letter-routing-key"、 "routingkey.dead"); //メッセージの優先度を設定すると、優先度の優先度が消費されます。arguments.put arguments.put( "x-max-priority"、10); channel.queueDeclare(QUEUE_NAME、false、false、false、arguments); channel.queueBind(QUEUE_NAME、EXCHANGE_NAME、 ""); 文字列メッセージ= "Hello RabbitMQ:"; for(int i = 1; i <= 5; i ++){ //有効期限:设置单条のメッセージの過期間 時間间AMQP.BasicProperties.Builderプロパティ= new AMQP.BasicProperties()。builder(). priority(i).expiration( i * 1000 + ""); channel.basicPublish(EXCHANGE_NAME、 ""、properties.build()、(message + i).getBytes( "UTF-8")); } channel.close(); connection.close();
15.メッセージキューを使用するデメリットは何ですか?
1.システムの可用性が低下します。他のシステムが正常に動作している限り、システムは正常であると考えます。ここで、メッセージキューを追加する必要があります。メッセージキューがハングします。システムは問題ありません。したがって、システムの可用性が低下します
2.システムの複雑さの増加:一貫性、メッセージが繰り返し消費されないようにする方法、メッセージの信頼できる伝送を保証する方法など、多くの問題を考慮する必要があります。したがって、考慮すべき事項が増え、システムの複雑さが増します。