ベストプラクティス
1プロデューサー
1.1メッセージ送信に関する注意事項
1タグの使用
アプリケーションは可能な限りトピックを使用し、メッセージのサブタイプはタグで識別できます。タグはアプリケーションによって自由に設定できます。メッセージの送信時にタグを設定できるのはプロデューサーのみであり、メッセージのサブスクライブ時にブローカーを介してメッセージをフィルタリングするためにコンシューマーが使用できるのは、message.setTags( "TagA")です。
2キーの使用
将来のメッセージ損失の問題の場所を特定しやすくするために、サービスレベルでの各メッセージの一意の識別コードをキーフィールドに設定する必要があります。サーバーはメッセージごとにインデックス(ハッシュインデックス)を作成し、アプリケーションはトピックとキー、およびメッセージの消費者ごとにメッセージのコンテンツを照会できます。これはハッシュインデックスであるため、ハッシュの衝突の可能性を回避するために、キーができるだけ一意であることを確認してください。
// 订单Id
String orderId = "20034568923546";
message.setKeys(orderId);
3ログ印刷
メッセージが正常に送信されたか失敗した場合は、メッセージログを印刷し、SendResultフィールドとキーフィールドを印刷する必要があります。メッセージ送信メソッドが例外をスローしない限り、メッセージが正常に送信されたことを意味します。送信が成功するためのステータスは複数あり、sendResultで定義されています。以下に、各状態について説明します。
- SEND_OK
メッセージは正常に送信されました。メッセージの成功は、それが信頼できることを意味しないことに注意する必要があります。メッセージが失われないようにするには、同期マスターサーバーまたは同期フラッシュ、つまりSYNC_MASTERまたはSYNC_FLUSHも有効にする必要があります。
- FLUSH_DISK_TIMEOUT
メッセージは正常に送信されましたが、サーバーのフラッシュがタイムアウトしました。この時点で、メッセージはサーバーキュー(メモリ)に入り、サーバーがダウンしている場合にのみメッセージが失われます。メッセージストレージ構成パラメーターで、フラッシュ方法と同期フラッシュ時間の長さを設定できます。ブローカーサーバーがフラッシュモードを同期フラッシュに設定している場合、つまり、ブローカーサーバーが同期フラッシュしていない場合はFlushDiskType = SYNC_FLUSH(デフォルトは非同期フラッシュモード)です。点滅時間(デフォルトは5秒)内に点滅が完了すると、この状態に戻ります-点滅タイムアウト。
- FLUSH_SLAVE_TIMEOUT
メッセージは正常に送信されましたが、スレーブと同期するときにサーバーがタイムアウトしました。この時点で、メッセージはサーバーキューに入り、サーバーがダウンしている場合にのみメッセージが失われます。ブローカーサーバーの役割が同期マスター、つまりSYNC_MASTER(デフォルトは非同期マスターまたはASYNC_MASTER)であり、スレーブブローカーサーバーが同期フラッシュ時間(デフォルトは5秒)内にマスターサーバーとの同期を完了しない場合、この状態に戻ります。 -スレーブサーバーへのデータ同期がタイムアウトしました。
- SLAVE_NOT_AVAILABLE
メッセージは正常に送信されましたが、現時点ではスレーブは使用できません。ブローカーサーバーの役割が同期マスター、つまりSYNC_MASTER(デフォルトは非同期マスターサーバー、つまりASYNC_MASTER)であるが、スレーブブローカーサーバーが構成されていない場合、この状態に戻ります。使用可能なスレーブサーバーはありません。
1.2メッセージ送信の失敗を処理する方法
Producer自体のsendメソッドは内部再試行をサポートしており、再試行ロジックは次のとおりです。
- 最大2回の複数回の試行(同期送信の場合は2回、非同期送信の場合は0回)。
- 送信に失敗した場合は、次のブローカーに進んでください。このメソッドの合計時間は、sendMsgTimeoutによって設定された値(デフォルトでは10秒)を超えません。
- ブローカー自体にメッセージを送信するとタイムアウト例外が生成された場合、ブローカーは再試行しません。
上記の戦略は、メッセージを正常に送信できることもある程度保証します。ビジネスでメッセージの信頼性に対する高い要件がある場合は、対応する再試行ロジックをアプリケーションに追加することをお勧めします。たとえば、送信同期メソッドが送信に失敗した場合は、メッセージをデータベースに保存してから、バックグラウンドスレッドで定期的に再試行して、メッセージがブローカーに到着するようにします。
上記のdb再試行方法がMQクライアントに統合されていないが、主に次の考慮事項に基づいて、アプリケーションがそれを完了する必要がある理由:まず、MQクライアントはステートレスモードで設計されており、任意の水平展開に便利です。マシンリソースの消費は、cpu、メモリ、およびネットワークのみです。次に、MQクライアントがKVストレージモジュールを統合している場合、データは信頼性を高めるために同期ディスクにのみ配置でき、同期ディスクのパフォーマンスオーバーヘッドは比較的高いため、通常は非同期ディスク配置が使用され、アプリケーションのシャットダウンプロセスはMQ操作の影響を受けません。保守要員の管理下では、kill -9が暴力的にシャットダウンされ、タイムリーに配置されていないためにデータが失われることがよくあります。第三に、プロデューサーが配置されているマシン、一般的には仮想マシンの信頼性は低く、重要なデータの保存には適していません。要約すると、再試行プロセスはアプリケーションによって制御されることをお勧めします。
1.3送信する一方向を選択します
通常、メッセージの送信は次のようなプロセスです。
- クライアントはサーバーにリクエストを送信します
- サーバー処理要求
- サーバーはクライアントに応答を返します
したがって、メッセージ送信にかかる時間は上記の3つのステップの合計であり、シナリオによっては非常に短い時間が必要ですが、一方向で呼び出すことができるログ収集アプリケーションなど、信頼性の要件は高くありません。一方向フォームは、応答を待たずに要求を送信するだけであり、要求の送信は、クライアント実装レベルでのオペレーティングシステムシステム呼び出しのオーバーヘッド、つまり、クライアントのソケットバッファへのデータの書き込みです。このプロセスには通常マイクロ秒かかります。
2人の消費者
2.1消費プロセスは同一です
RocketMQはメッセージの繰り返し(Exactly-Once)を回避できないため、ビジネスが消費の繰り返しに非常に敏感である場合は、ビジネスレベルで重複排除する必要があります。重複排除にはリレーショナルデータベースを使用できます。まず、メッセージの一意のキーを決定する必要があります。これは、msgId、または注文IDなどのメッセージコンテンツ内の一意の識別フィールドです。消費する前に、一意のキーがリレーショナルデータベースに存在するかどうかを確認してください。存在しない場合は挿入して消費し、存在しない場合はスキップします。(実際のプロセスでは、アトミック性の問題を考慮して、挿入の試みがあるかどうかを判断する必要があります。プライマリキーの競合が報告された場合、挿入は失敗し、直接スキップされます)
msgIdはグローバルに一意の識別子である必要がありますが、実際の使用では、同じメッセージに対して2つの異なるmsgIdが存在する場合があります(消費者の再送信、クライアントの再送信メカニズムによって引き起こされる繰り返しなど)。事業分野を繰り返し消費させる。
2.2遅い消費に対処する方法
1消費の並列性を改善する
メッセージの消費動作のほとんどはIOを集中的に使用します。つまり、データベースを操作している、またはRPCを呼び出している可能性があります。このタイプの消費動作の消費速度は、バックエンドデータベースまたは外部システムのスループットにあります。消費の並列処理を増やすことで、合計を改善できます。消費スループット、ただし並列度はある程度増加しますが、減少します。したがって、アプリケーションは妥当な程度の並列処理を設定する必要があります。消費の並列処理を変更するには、次のようにいくつかの方法があります。
- 同じConsumerGroupで、Consumerインスタンスの数を増やして、並列処理の度合いを増やします(サブスクリプションキューの数を超えるConsumerインスタンスは無効であることに注意してください)。マシンを追加したり、既存のマシンで複数のプロセスを開始したりできます。
- パラメーターconsumerThreadMinおよびconsumerThreadMaxを変更することにより、単一のコンシューマーの消費並列スレッドを改善します。
2バッチ消費
一部のビジネスプロセスがバッチ消費をサポートしている場合、消費スループットを大幅に向上させることができます。たとえば、注文控除アプリケーションでは、一度に1つの注文を処理するのに1秒かかり、一度に10の注文を処理するのに2秒しかかかりません。これにより、消費のスループットを大幅に向上させることができます。consumerMessageBatchMaxSizeパラメータを設定すると、デフォルトは1になります。つまり、一度に1つのメッセージのみが消費されます。たとえば、Nに設定すると、毎回消費されるメッセージの数はN以下になります。
3重要でないメッセージをスキップする
メッセージの蓄積が発生したときに、消費速度が送信速度に追いついていない場合、ビジネスが高いデータを必要としない場合は、重要でないメッセージを破棄することを選択できます。たとえば、特定のキュー内のメッセージの数が100,000を超える場合は、メッセージの一部またはすべてを破棄して、メッセージの送信速度にすばやく追いつくようにします。サンプルコードは次のとおりです。
public ConsumeConcurrentlyStatus consumeMessage(
List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
long offset = msgs.get(0).getQueueOffset();
String maxOffset =
msgs.get(0).getProperty(Message.PROPERTY_MAX_OFFSET);
long diff = Long.parseLong(maxOffset) - offset;
if (diff > 100000) {
// TODO 消息堆积情况的特殊处理
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
// TODO 正常消费过程
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
4各メッセージの消費プロセスを最適化します
たとえば、特定のメッセージの消費プロセスは次のとおりです。
- メッセージ[データ1]に従ってDBからクエリを実行します。
- メッセージ[データ2]に従ってDBからクエリを実行します。
- 複雑なビジネス計算
- [データ3]をDBに挿入
- [データ4]をDBに挿入
このメッセージの消費プロセス中にDBとのやり取りは4回あります。毎回5ミリ秒と計算すると、合計で20ミリ秒かかります。ビジネス計算に5ミリ秒かかるとすると、合計時間は25ミリ秒になるため、DBと4回やり取りできる場合最適化は2回で、合計時間は15ミリ秒に最適化できます。つまり、全体的なパフォーマンスが40%向上します。したがって、アプリケーションが遅延の影響を受けやすい場合は、SSDハードディスクにDBをデプロイできます。SCSIディスクと比較すると、前者のRTははるかに小さくなります。
2.3消費印刷ログ
メッセージの量が少ない場合は、その後のトラブルシューティングを容易にするために、時間などを消費する消費入力方式でメッセージを印刷することをお勧めします。
public ConsumeConcurrentlyStatus consumeMessage(
List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
log.info("RECEIVE_MSG_BEGIN: " + msgs.toString());
// TODO 正常消费过程
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
各メッセージを印刷して時間を消費できる場合は、消費が遅いなどのオンラインの問題をトラブルシューティングするときに便利です。
2.4その他の消費者の提案
1消費者とサブスクリプションについて
最初に注意することは、異なる消費者グループがいくつかのトピックを個別に消費でき、各消費者グループには独自の消費オフセットがあることです。同じグループ内の各消費者のサブスクリプション情報に一貫性があることを確認してください。 。
2整然としたメッセージについて
消費者は、各メッセージキューをロックして、1つずつ消費されるようにします。これによりパフォーマンスが低下しますが、メッセージの順序を気にする場合に役立ちます。例外をスローすることはお勧めしません。代わりにConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENTを返すことができます。
3同時消費について
名前が示すように、消費者はこれらのメッセージを同時に消費します。パフォーマンスを向上させるために使用することをお勧めします。例外をスローすることはお勧めしません。代わりにConsumeConcurrentlyStatus.RECONSUME_LATERを返すことができます。
4消費ステータス
同時消費リスナーの場合、RECONSUME_LATERを返して、メッセージを現在消費できないことを消費者に通知し、後で再び消費できることを期待できます。その後、他のメッセージを引き続き使用できます。順序付けされたメッセージリスナーの場合、順序を気にするため、メッセージをスキップすることはできませんが、SUSPEND_CURRENT_QUEUE_A_MOMENTを返して、しばらく待つようにコンシューマーに指示できます。
5ブロッキングについて
リスナーをブロックすると、スレッドプールがブロックされ、最終的にコンシューマプロセスが終了する可能性があるため、お勧めしません。
6スレッド数の設定について
コンシューマーはThreadPoolExecutorを使用してメッセージを内部で消費するため、setConsumeThreadMinまたはsetConsumeThreadMaxを設定してメッセージを変更できます。
7消費地について
新しいコンシューマーグループを作成するときは、ブローカーにすでに存在する履歴メッセージを消費する必要があるかどうかを決定する必要があります。CONSUME_FROM_LAST_OFFSETは、履歴メッセージを無視し、後で生成されたメッセージをすべて消費します。CONSUME_FROM_FIRST_OFFSETは、ブローカーに存在するすべての情報を消費します。CONSUME_FROM_TIMESTAMPを使用して、指定したタイムスタンプの後に生成されたメッセージを消費することもできます。
3ブローカー
3.1ブローカーの役割
ブローカーの役割は、ASYNC_MASTER(非同期マスター)、SYNC_MASTER(同期マスター)、およびSLAVE(スレーブ)に分けられます。メッセージの信頼性がより厳しい場合は、SYNC_MASTERとSLAVEの展開方法を使用できます。メッセージの信頼性が高くない場合は、ASYNC_MASTERとSLAVEデプロイメントモードを使用できます。テストにのみ便利な場合は、ASYNC_MASTERのみまたはSYNC_MASTERのみを展開することを選択できます。
3.2 FlushDiskType
SYNC_FLUSH(同期リフレッシュ)は、ASYNC_FLUSH(非同期処理)と比較してパフォーマンスが大幅に低下しますが、信頼性も高いため、実際のビジネスシナリオに基づいてトレードオフを行う必要があります。
3.3ブローカー構成
パラメータ名 | デフォルト | 説明 |
---|---|---|
listenPort | 10911 | クライアント接続を受け入れるリスニングポート |
namesrvAddr | ヌル | nameServerアドレス |
ブローカーIP1 | ネットワークカードのInetAddress | ブローカーによって現在監視されているIP |
ブローカーIP2 | ブローカーIP1と同じ | マスタースレーブブローカーが存在する場合、brokerIP2属性がブローカーマスターノードで構成されていると、ブローカースレーブノードはマスターノードによって構成されたbrokerIP2に接続して同期します。 |
ブローカー名 | ヌル | ブローカーの名前 |
ブローカークラスター名 | DefaultCluster | このブローカーが属するCluserの名前 |
ブローカーID | 0 | ブローカーID、0はマスターを意味し、他の正の整数はスレーブを意味します |
storePathCommitLog | $ HOME / store / commitlog / | コミットログを保存するパス |
storePathConsumerQueue | $ HOME / store / consumequeue / | 消費キューを格納するパス |
mapsFileSizeCommitLog | 1024 * 1024 * 1024(1G) | コミットログのマッピングファイルサイズ |
deleteWhen | 04 | ファイルの保持時間を超えたコミットログを削除する時刻 |
fileReservedTime | 72 | ファイルの保持時間(時間単位) |
ブローカーロール | ASYNC_MASTER | SYNC_MASTER / ASYNC_MASTER / SLAVE |
flushDiskType | ASYNC_FLUSH | SYNC_FLUSH / ASYNC_FLUSH SYNC_FLUSHモードのブローカーは、プロデューサーから確認を受信する前にメッセージをフラッシュすることを保証します。ASYNC_FLUSHモードのブローカーは、メッセージのグループをフラッシュするモードを使用して、パフォーマンスを向上させます。 |
4ネームサーバー
RocketMQでは、ネームサーバーは単純なルーティング管理用に設計されています。その責任は次のとおりです。
- ブローカーは定期的にルーティングデータを各ネームサーバーに登録します。
- ネームサーバーは、プロデューサー、コンシューマー、コマンドラインクライアントなどのクライアントに最新のルーティング情報を提供します。
5クライアント構成
RocketMQのブローカークラスターと比較すると、プロデューサーとコンシューマーの両方がクライアントです。このセクションでは、主にプロデューサーとコンシューマーのパブリックビヘイビアー構成について説明します。
5.1クライアントアドレス指定モード
RocketMQは、クライアントにネームサーバーを検索させ、次にネームサーバーを介してブローカーを検索させることができます。以下に示すように、複数の構成方法があり、優先度は高から低までで、高優先度が低優先度をオーバーライドします。
- コードでネームサーバーアドレスを指定し、複数のnamesrvアドレスをセミコロンで区切ります
producer.setNamesrvAddr("192.168.0.1:9876;192.168.0.2:9876");
consumer.setNamesrvAddr("192.168.0.1:9876;192.168.0.2:9876");
- Java起動パラメータでネームサーバーアドレスを指定します
-Drocketmq.namesrv.addr=192.168.0.1:9876;192.168.0.2:9876
- 環境変数は、ネームサーバーアドレスを指定します
export NAMESRV_ADDR=192.168.0.1:9876;192.168.0.2:9876
- HTTP静的サーバーアドレス指定(デフォルト)
クライアントが起動した後、定期的に静的HTTPサーバーにアクセスします。アドレスは次のとおりです。http://jmenv.tbsite.net:8080 / rocketmq / nsaddr、このURLの戻り内容は次のとおりです。
192.168.0.1:9876;192.168.0.2:9876
クライアントは、デフォルトで2分ごとにこのHTTPサーバーにアクセスし、ローカルのネームサーバーアドレスを更新します。URLはコードにハードコードされています。/etc/hostsファイルを変更することで、アクセスするサーバーを変更できます。たとえば、次の構成を/ etc / hostsに追加します。
10.232.22.67 jmenv.taobao.net
HTTP静的サーバーアドレス指定方法を使用することをお勧めします。利点は、クライアントの展開が簡単で、NameServerクラスターをホットアップグレードできることです。
5.2クライアント構成
DefaultMQProducer、TransactionMQProducer、DefaultMQPushConsumer、およびDefaultMQPullConsumerはすべて、クライアントのパブリック構成クラスであるClientConfigクラスから継承します。クライアントの構成は、getおよびsetの形式です。各パラメーターは、springまたはコードで構成できます。たとえば、パラメーターnamesrvAddrは、producer.setNamesrvAddr( "192.168.0.1:9876")、その他のパラメーターのように構成できます。同様に。
1クライアントのパブリック構成
パラメータ名 | デフォルト | 説明 |
---|---|---|
namesrvAddr | ネームサーバーアドレスリスト、複数のネームサーバーアドレスはセミコロンで区切られます | |
clientIP | ローカルIP | クライアントのローカルIPアドレス、一部のマシンはクライアントのIPアドレスを認識しないため、コードで強制的に指定する必要があります |
instanceName | デフォルト | クライアントインスタンスの名前。クライアントによって作成された複数のプロデューサーとコンシューマーは、実際には内部インスタンスを共有します(このインスタンスには、ネットワーク接続、スレッドリソースなどが含まれます)。 |
clientCallbackExecutorThreads | 4 | 通信層の非同期コールバックスレッドの数 |
pollNameServerInteval | 30000 | ネームサーバーのポーリング間隔(ミリ秒単位) |
heartbeatBrokerInterval | 30000 | ハートビートをブローカーに送信する間隔(ミリ秒単位) |
persistConsumerOffsetInterval | 5000 | 永続的な消費者消費の進行間隔(ミリ秒単位) |
2プロデューサー構成
パラメータ名 | デフォルト | 説明 |
---|---|---|
プロデューサーグループ | DEFAULT_PRODUCER | プロデューサーグループ名。複数のプロデューサーがアプリケーションに属し、同じメッセージを送信する場合、それらは同じグループにグループ化する必要があります。 |
createTopicKey | TBW102 | メッセージを送信する場合、サーバー上に存在しないトピックが自動的に作成され、キーを指定する必要があります。キーを使用して、メッセージが送信されるトピックのデフォルトルートを構成できます。 |
defaultTopicQueueNums | 4 | メッセージを送信し、サーバーが存在しないトピックを自動的に作成するときにデフォルトで作成されるキューの数 |
sendMsgTimeout | 10000 | メッセージ送信のタイムアウト(ミリ秒単位) |
compressMsgBodyOverHowmuch | 4096 | メッセージ本文が圧縮を開始するサイズを超えた場合(消費者はメッセージを受信すると自動的に解凍します)、バイト単位 |
TryAnotherBrokerWhenNotStoreOK | FALSE | メッセージを送信するとsendResultが返されますが、sendStatus!= SEND_OKの場合、送信を再試行するかどうか |
tryTimesWhenSendFailed | 2 | メッセージの送信に失敗した場合、最大再試行回数、このパラメーターは同期送信モードでのみ機能します |
maxMessageSize | 4MB | クライアントによって制限されたメッセージサイズはエラーを超えており、サーバーもエラーを制限するため、サーバーと組み合わせて使用する必要があります。 |
transactionCheckListener | トランザクションメッセージバックチェックリスナー、トランザクションメッセージを送信する場合は、設定する必要があります | |
checkThreadPoolMinSize | 1 | ブローカーがプロデューサートランザクションステータスをチェックするときのスレッドプール内のスレッドの最小数 |
checkThreadPoolMaxSize | 1 | ブローカーがプロデューサートランザクションステータスをチェックするときのスレッドプール内のスレッドの最大数 |
checkRequestHoldMax | 2000 | ブローカーがプロデューサーのトランザクションステータスを確認すると、プロデューサーローカルはリクエストキューサイズをバッファリングします |
RPCHook | ヌル | 该参数是在Producer创建时传入的,包含消息发送前的预处理和消息响应后的处理两个接口,用户可以在第一个接口中做一些安全控制或者其他操作。 |
3 PushConsumer配置
参数名 | 默认值 | 说明 |
---|---|---|
consumerGroup | DEFAULT_CONSUMER | Consumer组名,多个Consumer如果属于一个应用,订阅同样的消息,且消费逻辑一致,则应该将它们归为同一组 |
messageModel | CLUSTERING | 消费模型支持集群消费和广播消费两种 |
consumeFromWhere | CONSUME_FROM_LAST_OFFSET | Consumer启动后,默认从上次消费的位置开始消费,这包含两种情况:一种是上次消费的位置未过期,则消费从上次中止的位置进行;一种是上次消费位置已经过期,则从当前队列第一条消息开始消费 |
consumeTimestamp | 半个小时前 | 只有当consumeFromWhere值为CONSUME_FROM_TIMESTAMP时才起作用。 |
allocateMessageQueueStrategy | AllocateMessageQueueAveragely | Rebalance算法实现策略 |
subscription | 订阅关系 | |
messageListener | 消息监听器 | |
offsetStore | 消费进度存储 | |
consumeThreadMin | 10 | 消费线程池最小线程数 |
consumeThreadMax | 20 | 消费线程池最大线程数 |
consumeConcurrentlyMaxSpan | 2000 | 单队列并行消费允许的最大跨度 |
pullThresholdForQueue | 1000 | 拉消息本地队列缓存消息最大数 |
pullInterval | 0 | 拉消息间隔,由于是长轮询,所以为0,但是如果应用为了流控,也可以设置大于0的值,单位毫秒 |
consumeMessageBatchMaxSize | 1 | 批量消费,一次消费多少条消息 |
pullBatchSize | 32 | 批量拉消息,一次最多拉多少条 |
4 PullConsumer配置
参数名 | 默认值 | 说明 |
---|---|---|
consumerGroup | DEFAULT_CONSUMER | Consumer组名,多个Consumer如果属于一个应用,订阅同样的消息,且消费逻辑一致,则应该将它们归为同一组 |
brokerSuspendMaxTimeMillis | 20000 | 长轮询,Consumer拉消息请求在Broker挂起最长时间,单位毫秒 |
consumerTimeoutMillisWhenSuspend | 30000 | 长轮询,Consumer拉消息请求在Broker挂起超过指定时间,客户端认为超时,单位毫秒 |
consumerPullTimeoutMillis | 10000 | 非长轮询,拉消息超时时间,单位毫秒 |
messageModel | BROADCASTING | 消息支持两种模式:集群消费和广播消费 |
messageQueueListener | 监听队列变化 | |
offsetStore | 消费进度存储 | |
registerTopics | 注册的topic集合 | |
allocateMessageQueueStrategy | AllocateMessageQueueAveragely | Rebalance算法实现策略 |
5 Message数据结构
字段名 | 默认值 | 说明 |
---|---|---|
Topic | null | 必填,消息所属topic的名称 |
Body | null | 必填,消息体 |
Tags | null | 选填,消息标签,方便服务器过滤使用。目前只支持每个消息设置一个tag |
Keys | null | 选填,代表这条消息的业务关键词,服务器会根据keys创建哈希索引,设置后,可以在Console系统根据Topic、Keys来查询消息,由于是哈希索引,请尽可能保证key唯一,例如订单号,商品Id等。 |
Flag | 0 | 选填,完全由应用来设置,RocketMQ不做干预 |
DelayTimeLevel | 0 | 选填,消息延时级别,0表示不延时,大于0会延时特定的时间才会被消费 |
WaitStoreMsgOK | TRUE | 选填,表示消息是否在服务器落盘后才返回应答。 |
6 系统配置
本小节主要介绍系统(JVM/OS)相关的配置。
6.1 JVM选项
推荐使用最新发布的JDK 1.8版本。通过设置相同的Xms和Xmx值来防止JVM调整堆大小以获得更好的性能。简单的JVM配置如下所示:
-server -Xms8g -Xmx8g -Xmn4g
如果您不关心RocketMQ Broker的启动时间,还有一种更好的选择,就是通过“预触摸”Java堆以确保在JVM初始化期间每个页面都将被分配。那些不关心启动时间的人可以启用它: -XX:+AlwaysPreTouch
禁用偏置锁定可能会减少JVM暂停, -XX:-UseBiasedLocking
至于垃圾回收,建议使用带JDK 1.8的G1收集器。
-XX:+UseG1GC -XX:G1HeapRegionSize=16m
-XX:G1ReservePercent=25
-XX:InitiatingHeapOccupancyPercent=30
这些GC选项看起来有点激进,但事实证明它在我们的生产环境中具有良好的性能。另外不要把-XX:MaxGCPauseMillis的值设置太小,否则JVM将使用一个小的年轻代来实现这个目标,这将导致非常频繁的minor GC,所以建议使用rolling GC日志文件:
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=30m
如果写入GC文件会增加代理的延迟,可以考虑将GC日志文件重定向到内存文件系统:
-Xloggc:/dev/shm/mq_gc_%p.log123
6.2 Linux内核参数
os.sh脚本在bin文件夹中列出了许多内核参数,可以进行微小的更改然后用于生产用途。下面的参数需要注意,更多细节请参考/proc/sys/vm/*的文档
- vm.extra_free_kbytes,告诉VM在后台回收(kswapd)启动的阈值与直接回收(通过分配进程)的阈值之间保留额外的可用内存。RocketMQ使用此参数来避免内存分配中的长延迟。(与具体内核版本相关)
- vm.min_free_kbytes,如果将其设置为低于1024KB,将会巧妙的将系统破坏,并且系统在高负载下容易出现死锁。
- vm.max_map_count,限制一个进程可能具有的最大内存映射区域数。RocketMQ将使用mmap加载CommitLog和ConsumeQueue,因此建议将为此参数设置较大的值。(agressiveness --> aggressiveness)
- vm.swappiness,定义内核交换内存页面的积极程度。较高的值会增加攻击性,较低的值会减少交换量。建议将值设置为10来避免交换延迟。
- File descriptor limits,RocketMQ需要为文件(CommitLog和ConsumeQueue)和网络连接打开文件描述符。我们建议设置文件描述符的值为655350。
- Disk scheduler,RocketMQ建议使用I/O截止时间调度器,它试图为请求提供有保证的延迟。