Alibaba Cloud パフォーマンス テスト ツール JMeter を使用してシナリオで RocketMQ をストレス テストするためのベスト プラクティス

著者:森本

需要の背景

新しいビジネスをオンラインにする前に、通常、システムのさまざまなミドルウェアでストレス テストを実施し、現在の構成でミドルウェアが耐えられるトラフィックの上限を見つけ、上流の現在の制限ルールを決定する必要があります。突然のトラフィックによるシステムの崩壊を防ぐためのリンク。Alibaba Cloud PTS の JMeter ストレス テストは、ユーザーによるカスタム JMeter スクリプトのアップロードをサポートし、PTS の強力な分散ストレス テスト機能を使用して、カスタム ロジックに従ってシステムのさまざまなミドルウェアでストレス テストを実行できます。以下では、JMeter5.5 および RocketMQ5.0 シリーズを例として、PTS の JMeter シナリオを使用して RocketMQ のストレス テストを行う方法を詳しく紹介します。

前提条件

  1. JMeter はローカルにインストールされます。
  2. RocketMQ は Alibaba Cloud ECS にデプロイされています (この記事では 8C32G 仕様の ECS を選択しました)。
  3. Alibaba Cloud 上で PTS サービスが有効化されました。

ストレステストのプロセス

JMeter は拡張性の高い JavaSampler を提供しており、AbstractJavaSamplerClient クラスを継承することで JavaSampler で実行されるロジックをカスタマイズし、RocketMQ のストレス テストを実装できます。

ステップ 1: Maven プロジェクトを作成し、依存関係を導入する

  1. 新しい Maven プロジェクトを作成し、pom ファイルに次の依存関係を導入します。
<dependency>
  <groupId>org.apache.jmeter</groupId>
  <artifactId>ApacheJMeter_java</artifactId>
  <version>5.5</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>org.apache.rocketmq</groupId>
  <artifactId>rocketmq-client</artifactId>
  <version>4.9.5</version>
</dependency>

ApacheJMeter_java は JMeter JavaSampler の依存関係であり、rocketmq-client は RocketMQ のクライアント依存関係です (バージョン 4.x のクライアントはバージョン 5.x のサーバー インスタンスと互換性があるため、ここではバージョン 4.x が使用されますが、バージョン 5 .x クライアントはバージョン 4.x のサーバー インスタンスと互換性がありませんが、必要に応じて調整できます)。このうち、ApacheJMeter_java の依存関係のスコープは規定どおりに定義されており、JAR パッケージは JMeter の lib/ext ディレクトリにすでに用意されているため、依存関係を一緒にパッケージ化する必要はありません。

  1. maven-assembly-plugin プラグインを pom ファイルに導入し、ここで「jar-with-dependency」パッケージ化メソッドを使用して、プロジェクトに必要な依存関係とプロジェクト コードを同じ JAR パッケージにパッケージ化します。その後、JAR のみをアップロードできます。 JMeter 環境では、複数の依存 JAR パッケージをアップロードする必要はありません。
<build>
  <finalName>jmeter-rocketmq4</finalName>
  <plugins>
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <version>3.4.2</version>
      <configuration>
        <!-- 打包方式 -->
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
      </configuration>
      <executions>
        <execution>
          <id>make-assembly</id>
          <phase>package</phase>
          <goals>
            <goal>single</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

ステップ 2: AbstractJavaSamplerClient の新しいサブクラスを作成し、関連メソッドを書き直す

AbstractJavaSamplerClient クラスは JavaSamplerClient インターフェイスを継承します。このインターフェイスには、setupTest、runTest、teardownTest、getDefaultParameters の 4 つのメソッドが含まれています。

  • セットアップテスト

    JMeter は、テスト内の各スレッドの JavaSamplerClient 実装インスタンスを作成します。テストが開始されると、クライアントを初期化するために各スレッドの JavaSamplerClient インスタンスで setupTest が呼び出されます。この場合、RocketMQ プロデューサが初期化されます。

  • 実行テスト

    各スレッドは繰り返しごとに runTest メソッドを呼び出しますが、この例では、メッセージの送信メソッドとサンプリング結果の設定ロジックを runTest メソッドで定義する必要があります。

  • 分解テスト

    設定した回数または時間を繰り返した後、このメソッドが実行されますが、この例では、このメソッド内でプロデューサを閉じる必要があります。

  • getDefaultParameters

    このメソッドは、JavaSamplerContext を通じて上記のメソッドに渡されるパラメータ リストを定義します。このメソッドで定義されたパラメータは、JMeter JavaRequest Sampler の GUI インターフェイスで設定できます。この例では、RocketMQ のブローカ アドレスとトピック名が必要です、メッセージキー、メッセージコンテンツ、その他のパラメータを定義します。

新しいサブクラスを作成するためのリファレンスは次のとおりです。

import java.nio.charset.StandardCharsets;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;

public class JavaSamplerForRocketMQ extends AbstractJavaSamplerClient {
    private DefaultMQProducer producer;
    private static final String NAME_SRV_ADDRESS = "nameSrvAddress";
    private static final String TOPIC = "topic";
    private static final String PRODUCER_GROUP = "producer group";
    private static final String MSG_BODY = "messageBody";
    private static final String MSG_KEY = "messageKey";
    private static final String MSG_TAG = "messageTag";
    private static final String ERROR_CODE = "500";

    @Override
    public void setupTest(JavaSamplerContext javaSamplerContext) {

        try {
            // 初始化producer
            producer = new DefaultMQProducer(javaSamplerContext.getParameter(PRODUCER_GROUP));
            producer.setNamesrvAddr(javaSamplerContext.getParameter(NAME_SRV_ADDRESS));
            producer.start();
        } catch (MQClientException e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public SampleResult runTest(JavaSamplerContext javaSamplerContext) {
        SampleResult sampleResult = new SampleResult();
        sampleResult.setSampleLabel("rocketmq-producer");
        // 请求开始
        sampleResult.sampleStart();
        // 普通消息发送
        Message message = new Message(
            javaSamplerContext.getParameter(TOPIC),
            javaSamplerContext.getParameter(MSG_TAG),
            javaSamplerContext.getParameter(MSG_BODY).getBytes()
        );
        try {
            // 发送消息,需要关注发送结果,并捕获失败等异常。
            SendResult sendResult = producer.send(message);
            // 设置发送请求的字节数
            sampleResult.setSentBytes(message.toString().getBytes(StandardCharsets.UTF_8).length);
            sampleResult.setDataType(SampleResult.TEXT);
            // 设置请求内容
            sampleResult.setSamplerData(message.toString());
            // 设置响应内容
            sampleResult.setResponseData(String.format("Msg Id:%s", sendResult.getMsgId()).getBytes());
            sampleResult.setSuccessful(true);
            sampleResult.setResponseCodeOK();
        } catch (MQBrokerException | InterruptedException | RemotingException | MQClientException e) {
            sampleResult.setSuccessful(false);
            sampleResult.setResponseCode(ERROR_CODE);
            sampleResult.setResponseData(String.format("Error Msg:%s", e).getBytes());
            return sampleResult;
        } finally {
            // 请求结束
            sampleResult.sampleEnd();
        }
        return sampleResult;
    }

    @Override
    public void teardownTest(JavaSamplerContext javaSamplerContext) {
        producer.shutdown();
    }

    @Override
    public Arguments getDefaultParameters() {
        Arguments arguments = new Arguments();
        arguments.addArgument(NAME_SRV_ADDRESS, "");
        arguments.addArgument(PRODUCER_GROUP, "");
        arguments.addArgument(TOPIC, "");
        arguments.addArgument(MSG_KEY, "");
        arguments.addArgument(MSG_TAG, "");
        arguments.addArgument(MSG_BODY, "");
        return arguments;
    }
}

ステップ 3: プロジェクトを JAR ファイルにパッケージ化する

mvn clean package を通じてプロジェクトをパッケージ化します。ターゲット ディレクトリには、jmeter-rocketmq4.jar と jmeter-rocketmq4-jar-with-dependency.jar という 2 つの JAR パッケージが表示されます。 .jar には必要な依存関係がすべて含まれています。後続の手順でこの JAR パッケージを使用します。

.
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── JavaSamplerForRocketMQ4.java
│   │   └── resources
│   └── test
│       └── java
└── target
    ├── jmeter-rocketmq4-jar-with-dependencies.jar
    ├── jmeter-rocketmq4.jar

ステップ 4: JMeter GUI を使用してスクリプト作成とデバッグを行う

  1. パッケージ化された JAR パッケージと依存する JAR パッケージを JMETER_HOME/lib/ext ディレクトリにコピーし、コマンド JMETER_HOME/bin/jmeter を実行して JMeter GUI を開きます。

  2. 新しいスレッド グループを作成した後、Java リクエスト サンプラーを追加します。

  1. ドロップダウン ボックスで、手順 2 で追加したクラスを選択し (図とまったく同じではない場合があります。クラスの実際の完全修飾名に従って選択します)、以下の関連パラメータを入力します。

  1. 「結果ツリーの表示」リスナーと「概要レポート」リスナーをスレッド グループに追加し、テスト計画を開始して、テストの結果が結果ツリーと概要レポートで期待どおりであるかどうかを確認します。

  2. テスト計画を JMX ファイルとして保存します。

ステップ 5: ストレス テスト用に PTS で JMeter シナリオを作成する

  1. PTS コンソールで JMeter 環境を作成し、手順 3 でパッケージ化された JAR パッケージを JMeter 環境にアップロードします (詳細については、「JMeter 環境の表示、変更、および作成」を参照してください。 管理_パフォーマンス テスト - Alibaba Cloud ヘルプセンター[ 1] )。

a. PTS コンソールに入り、「JMeter 環境」を選択します。

b. カスタマイズした環境名を入力します。

c. クリックしてファイルをアップロードし、手順 3 でパッケージ化した JAR パッケージを選択します。

d. 「保存」をクリックします。

  1. PTS コンソール作成シナリオで「JMeter Stress Test」シナリオを選択します。

  1. 「シーン構成」を編集します。

a. カスタムシーン名。

b. [ファイルのアップロード] をクリックし、手順 4 で保存した JMX ファイルを選択します。

c. [依存環境を使用しますか?] ドロップダウン ボックスで [はい、依存環境を使用します] を選択します。

d. [依存環境の選択] ドロップダウン ボックスで、作成したばかりの JMeter 環境を選択します。

  1. 圧力構成:

小さな提案: RocektMQ がストレス テストを通じて耐えられる同時リクエストの最大数を確認したいため、RocektMQ の耐圧能力を直接測定できる RPS モードを選択することをお勧めします。同時に、パブリック ネットワーク帯域幅の制限を考慮して、Alibaba Cloud VPC イントラネット ストレス テストを選択する必要があります。

a. 圧力ソースとして Alibaba Cloud VPC イントラネットを選択し、ストレス テスト用に RocketMQ がデプロイされている ECS が配置されているリージョンを選択します。

b. ECS の VPC、セキュリティ グループ、スイッチを設定します。VPC とセキュリティ グループは ECS と同じである必要があり、対応するポートがセキュリティ グループ (ECS コンソールで設定) で開かれている必要があることに注意してください。

c. 圧力モードを RPS モードに設定します。

d. 開始 RPS、最大 RPS、およびストレス テスト期間を設定します。この記事では、開始 RPS を 90000 に、最大 RPS を 2 分間 110000 に設定します。

e. 指定されたループは通常 [いいえ] に設定され、1 回実行されて終了することを意味し、指定された IP 番号は設定された RPS に従って自動的に生成されます。

  1. 残りの設定については、必要に応じて、JMeter Stress Test_Performance Test-Alibaba Cloud ヘルプセンター[ 2]を参照してください。

  2. 構成を保存してシナリオをデバッグし、RocketMQ との接続を確認してから、ストレス テストを開始します。

ステップ 6: ストレス テスト レポートを表示する

JMeter のストレス テスト レポートの一般的な解釈については、「JMeter ストレス テスト データ、サンプリング ログ、および圧力アプリケーターの表示方法」_パフォーマンス テスト - Alibaba Cloud ヘルプ センター[ 3]を参照してください。次のセクションでは、PTS のストレス テスト レポートを使用して次のことを確認する方法を紹介します。 RocketMQ の耐圧能力。

レポートの解釈

  1. まず、ストレス テスト全体の概要情報と指標の傾向を表示します。以下の図に示すように、レポートの最初の列には、ストレス テスト プロセス全体のリクエスト成功率、平均 RT、平均 TPS などの指標が示されており、これらの指標の具体的な説明は公式ドキュメントに記載されています。同時に、成功率推移グラフによると、18:54:05 から徐々に成功率が変動して減少しており、この時の TPS 値は 9.55W で、最初の 5 秒間の平均 TPS を意味します。 18:54:05で計算すると約9.55Wです。

  1. 次に、ストレス テスト レポートの Prometheus モニタリング データを使用して、結果をさらに分析します。Alibaba Cloud ARMS の Prometheus および Grafana 製品の助けを借りて、PTS のストレス テスト レポートは、スループット、成功率、応答時間を含むタイミング図を提供できます。同時に、ユーザーは PromQL ステートメントを使用してデータ パネルを編集し、必要なクエリを柔軟に実行できます。この記事では、成功率とスループットをパネルに入力してさらに分析できます。

a. まず [成功率 (時系列)] をクリックし、次に [編集] をクリックして成功率ダッシュボードの編集インターフェイスに入り、成功率クエリ PromQL をコピーします。

sum(rate(pts_api_response_total{task_id="$task_id", code=~"200|302"}[5s]))/sum(rate(pts_api_response_total{task_id="$task_id"}[5s]))

b. 次に、スループット ダッシュボードの編集インターフェイスに入り、仮想ユーザー数の PromQL を成功率の PromQL に置き換え、Grafana の関連構成 (下図の赤いボックス) を変更すると、スループットと成功率を示すパネル。

このパネルに表示されるデータの統計精度は 1 秒であり、より正確なデータを取得できますが、18:54:05 秒から成功率が低下し始め、この時点の TPS は 96561.9 です。

c. RocketMQ のパフォーマンスをより適切に評価するために、成功率が 100% である時間範囲内の平均 TPS を計算することもできます。まず、成功率が 100% である期間 (図では 47 秒) を求めます。 TPS インジケーターの時間範囲が 47 秒に変更され、各ポイントが過去 47 秒の平均 TPS を表します。成功率が 100% である最後の時間にマウスを移動します。その時点の TPS 値は、現在の時間は成功率 100% の時間範囲であり、その範囲内の平均 TPS は 89357.5 です。

  1. 最後に、RocketMQ のパフォーマンスに対するさまざまなパラメーター設定の影響を比較し、RocketMQ ストレス テストでの PTS の可用性を検証するために、簡単な比較実験を実施し、jstat コマンドを使用して、ガベージ コレクションに対するさまざまなパラメーターの影響を観察しました。

実験結果は、現在の ECS 構成でデプロイされた RocketMQ の場合、ヒープ メモリを適切に増やすことで RocketMQ のパフォーマンスを効果的に向上できることを示しています。ヒープ メモリを 24g に増やすと (この場合、ECS メモリ使用量は 85.39% に達します)、パフォーマンスはsendMessageThreadPoolNums の値を増やすと、RocketMQ のパフォーマンスが向上します。sendMessageThreadPoolNums が 16 を超えると、パフォーマンスはあまり向上しないか、わずかに低下することもあります。ユーザーは、実際の条件に基づいてより詳細な比較実験を実施し、展開された RocketMQ の耐圧能力を完全に評価できます。

結論

この記事では、Alibaba Cloud PTS の JMeter シナリオを使用して RocketMQ をストレス テストする詳細な手順を紹介し、各リンクを 1 つずつ説明します。最後に、ストレス テスト レポートのカスタマイズされた分析を通じて、PTS の強力なストレス テスト結果分析機能を示します。 JMeter と PTS の助けを借りて、ユーザーはさまざまな種類のミドルウェアに対して柔軟かつ多次元の分析を実行して、安定した堅牢なシステムを構築することができます。

最新のイベントと無料トライアル

関連リンク:

[1] JMeter 環境管理の表示、変更、作成_パフォーマンス テスト-Alibaba Cloud ヘルプセンター

https://help.aliyun.com/document_detail/170857.html?spm=a2c4g.103173.0.0.292c20f8wnWyCV

[2] JMeter ストレステスト_パフォーマンステスト-Alibaba Cloud ヘルプセンター

https://help.aliyun.com/document_detail/97876.html?spm=a2c4g.91788.0.0.2fde6f338aHIDI

[3] JMeter ストレス テスト データ、サンプリング ログ、圧力マシンのパフォーマンスを表示する方法_パフォーマンス テスト-Alibaba Cloud ヘルプセンター

https://help.aliyun.com/document_detail/127454.html?spm=a2c4g.94066.0.0.4a5164bepHmzWD

有名なオープンソース プロジェクトの作者が躁状態で職を失った - 「オンラインでお金を求めている」 スターなし、修正なし 2023 年世界のエンジニアリング成果トップ 10 が発表: ChatGPT、Hongmeng オペレーティング システム、中国宇宙ステーション、その他の選ばれた ByteDance Google、2023 年に最も人気のある Chrome 拡張機能を発表学者 の倪光南氏: Xiaomi 携帯電話 BL のロックを解除するために、 輸入 HDD を国産 SSD に置き換えることを願っていますか? まず、Java プログラマーの面接の質問をします. Arm が 70 人以上の中国人エンジニアを解雇し、中国のソフトウェア ビジネスの再編を計画. OpenKylin 2.0 が明らかに | UKUI 4.10 ダブル ダイヤモンド デザイン、美しく高品質! Manjaro 23.1 リリース、コード名は「Vulcan」
{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/3874284/blog/10322817