メッセージミドルウェア-テクニカルゾーン-RabbitMQの一般的なインタビューの質問

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.システムの複雑さの増加:一貫性、メッセージが繰り返し消費されないようにする方法、メッセージの信頼できる伝送を保証する方法など、多くの問題を考慮する必要があります。したがって、考慮すべき事項が増え、システムの複雑さが増します。

おすすめ

転載: www.cnblogs.com/liboware/p/12673446.html