[メッセージキュー] RocketMQクラスターの展開を本番環境の障害からロック解除するためのベストプラクティス

I.はじめに

年末近くに、作成者が保守している本番MQクラスターの物理マシンメモリ障害により、オペレーティングシステムが異常に再起動しました。10分以内に、多くのアプリケーション送信クライアントでメッセージ送信タイムアウトが発生しました。事故はS1、著者の「年末ボーナス」...

1.1障害の説明

RocketMQクラスターで採用されているデプロイメントアーキテクチャは、2つのマスターと2つのスレーブです。デプロイメントアーキテクチャを次の図に示します。

そのデプロイメントアーキテクチャの非常に明白な機能は、物理マシンへのネームサーバーおよびブローカープロセスのデプロイメントです。

マシンの1つ(192.168.3.100)でメモリ障害が発生し、マシンが再起動しましたが、Linuxオペレーティングシステムの再起動に必要なセルフチェックなどの要因により、再起動プロセス全体が10分近く続きました。クライアントの送信タイムアウトは10分間続きました。これは明らかに受け入れられません!

RocketMQの高可用性設計とは何ですか?次に、分析プロセスについて詳しく説明します。

1.2故障解析

RocketMQクラスターは障害の検出と回復を自然にサポートする分散展開アーキテクチャであり、メッセージの送信が行われるため、マシンの障害によってメッセージ送信のタイムアウトが10分間続くことを知ったとき、最初の反応はそうすべきではないというものでした。クライアントはブローカーを自動的に認識できます。異常な時間が10分を超えることはありませんが、どのようにして障害が発生したのでしょうか。

まず、RocketMQのルーティング登録と検出メカニズムを確認しましょう。

(1)RocketMQルーティングの登録および削除メカニズム

ルーティングの登録と削除のメカニズムは次のとおりです。

  • クラスター内のすべてのブローカーは、30秒ごとにクラスター内のすべてのネームサーバーにハートビートパケットを送信して、トピックルーティング情報を登録します。
  • ネームサーバーはブローカー側からハートビートパケットを受信すると、最初にルーティングテーブルを更新し、ハートビートパケットが受信された時刻を記録します。
  • NameServerは、スケジュールされたタスクを開始して、ブローカーのサバイバルステータステーブルを10秒ごとにスキャンします。ネームサーバーがブローカーのハートビートパケットを120秒間受信しない場合、ブローカーはオフラインであると判断し、ルーティングテーブルからブローカーを削除します。
  • ネームサーバーとブローカーの間の長い接続が切断された場合、ネームサーバーはブローカーがオフラインであることを即座に検知し、ルーティングテーブルからブローカーを削除します。
  • メッセージクライアント(メッセージ送信者、メッセージコンシューマー)は、いつでもネームサーバーの1つとの接続を確立し、30秒ごとにネームサーバーにルーティング情報を照会します。照会結果が見つかると、クライアントのローカルルーティング情報が更新されます。ルーティングが照会された場合失敗した場合は無視します。

上記のルーティング登録および削除メカニズムから判断すると、ブローカーサーバーがダウンしている場合、メッセージ送信者がルーティング情報の変更を認識するのにどのくらい時間がかかりますか?

次の2つの状況で別々に話し合います。

  • ネームサーバーとブローカーサーバー間のTCP接続が切断されます。この時点で、ネームサーバーはルーティング情報の変更をすぐに認識してルーティングテーブルから削除できるため、メッセージ送信者は30秒以内にルーティング情報の変更を認識できるはずです。送信者は、メッセージの送信に失敗したが、送信回避メカニズムと組み合わせた場合、送信者に重大な障害を引き起こすことはありません。これは許容範囲です。
  • ネームサーバーとブローカーサーバー間のTCP接続が切断されていないが、ブローカーがサービス(中断されたアニメーションなど)を提供できなくなった場合、ネームサーバーがブローカーのダウンタイムを検出するのに120秒かかり、この時点でメッセージが表示されます。送信者は、ルーティング情報の変更を検知するために最大150秒必要です。

しかし、問題は、なぜブローカーがメモリ障害のために再起動し、ビジネスが10分後に再開するのか、つまり、クライアントがブローカーがダウンしていることを本当に感知するのかということです。

表示されたので、それを分析して、本番環境で同じタイプのエラーを回避するための解決策を提供する必要があります。

(2)トラブルシューティング後

クライアントのログ(/home/{user}/logs/rocketmqlogs/rocketmq_client.log)をクエリすると、クライアントからメッセージを初めて送信した時刻が14:44であることがわかります。ログ出力は次のとおりです。次のとおりです。

192.168.3.100マシンのメモリ障害が原因で、最初にクラスター内の他のネームサーバーのログをチェックして、通常のマシンのNameServerがブローカーaの障害を認識する時間を確認します。ログは次のとおりです。

このことから、192.18.3.101のネームサーバーは基本的に約2分でダウンタイムを検知していることがわかります。つまり、マシンは再起動していますが、オペレーティングシステムのハードウェアセルフチェックのためにTCP接続が切断されていない可能性があります。他の理由で、ネームサーバーは120秒後にダウンタイムを検知し、ルーティング情報テーブルからブローカーを削除します。次に、ルーティング除去メカニズムに従って、クライアントは150秒以内に変更を認識しなければならないのに、なぜそれを認識しなかったのでしょうか。 ?

次の図に示すように、引き続きクライアントのルーティング情報を表示し、クライアントがルーティング情報の変更を認識した時点を表示します。

クライアントログから、クライアントは14:53:46にのみ変更を認識します。これはなぜですか?

ルーティング情報を更新するときに、クライアントがタイムアウト例外を報告したことが判明しました。スクリーンショットを以下に示します

障害から障害回復までの期間、クライアントは障害のあるネームサーバーからルーティング情報を更新しようとしましたが、常にタイムアウトが返され、クライアントは最新のルーティング情報を取得できませんでした。ダウンしていることを感知できませんでした。ブローカー。

ログ分析の観点からは、これまでのところ比較的明確です。クライアントがダウンしたネームサーバーからルーティング情報を更新しようとしているため、120秒以内にすべてのクライアントがルーティング情報の変更を認識しませんでした。リクエストが成功しなかったため、クライアントのキャッシュされたルーティング情報を更新できず、上記の現象が発生しました

問題はここにあります。RocketMQの理解によると、ネームサーバーがダウンしており、クライアントはネームサーバーリストから次のネームサーバーを自動的に選択します。ネームサーバーの切り替えここ発生しないのはなぜですか。14:53まで待ちますか?

次に、ネームサーバースイッチングコードに焦点を当てます。コードスニペットを次の図に示します。

上図のいくつかの重要な分析は次のとおりです。

  • クライアントがキャッシュから接続を選択してRPC要求を送信するための前提条件は、接続のisActiveメソッドがtrueを返すこと、つまり、基になるTCP接続がアクティブであることです。
  • クライアントがサーバーへのRPC要求を開始するときに、タイムアウト以外の例外が発生すると、closeChannelメソッドが実行されます。このメソッドは、接続を閉じて接続キャッシュテーブルから削除します。これは非常に重要です。ネームサーバーを切り替えるときのキャッシュ接続がアクティブで接続がアクティブな場合、ネームサーバーは切り替えられません。
  • 送信RPCがタイムアウトした場合、rocketmqはclientCloseSocketIfTimeoutパラメーターに従って接続を閉じるかどうかを決定しますが、残念ながら、このパラメーターはデフォルトでfalseであり、変更エントリは提供されません。

ここでの問題の分析は非常に明確です。

再起動をトリガーするマシンメモリ障害やセルフチェックの必要性などの要因により、ネームサーバーとブローカーは要求を処理できなくなりますが、基盤となるTCP接続は切断されません。タイムアウト後に戻りますが、クライアントは戻りません。障害が発生したマシンネームサーバーとのTCP接続を閉じます。これにより、NameServerの切り替えがトリガーされます。マシンが正常に再起動すると、TCP接続が切断されます。障害のあるマシンが再起動すると、ルーティング情報の変更が検出され、障害から回復します。

根本原因:ネームサーバーの一時停止されたアニメーションにより、ルーティング情報の更新に失敗しました。

(3)ベストプラクティス

上記の失敗の後、私は個人的にネームサーバーをブローカーと一緒にデプロイすべきではないと感じています。ネームサーバーとブローカーを一緒にデプロイしない場合、上記の問題を効果的に回避できます。デプロイメントアーキテクチャを次の図に示します。

そのようなデプロイメントアーキテクチャが上記のシナリオ、つまりブローカーの仮死状態に直面した場合、それを効果的に回避できますか?答えはイエスです。

192.168.3.100のブローカーが一時停止されている場合、3.110および3.111のネームサーバーはブローカーaが2分以内にダウンしていることを認識でき、クライアントはネームサーバーから最新のルーティング情報を取得できるため、継続しません。メッセージが送信されるとダウンブローカーはメッセージを送信し続け、障害が復元されます。

ネームサーバーが一時停止してタイムアウトエラーが発生した場合、ブローカーがダウンしていない限り、キャッシュは正常に機能しますが、nanmeserverとブローカーが一緒に一時停止した場合でも、上記のアーキテクチャでは上記の問題を回避できません

そのため、ベストプラクティス、この時間は、主に以下の2つの指標が含まれて
1.ネームサーバとブローカーは個別にデプロイし、隔離する必要があります。
2.ネームサーバーのドリフトをトリガーするには、タイムアウト後にネームサーバーとクライアント間の接続を閉じる必要があり、ソースコードを変更する必要があります。

 

 

 

 

 

 

 

 

 

 

おすすめ

転載: blog.csdn.net/qq_41893274/article/details/112546934