awesome-hacks
Docs

JMeterで負荷テストを始める

Apache JMeterの基本概念・コンポーネントの理解からTest Planの作成、CLI実行、HTMLレポートの確認まで

最終更新:2026/06/05

この記事でやること

  • JMeterをインストールする
  • 主要コンポーネントを理解する
  • テスト対象のHTTPサーバーを用意する(Node.js組み込みモジュールで3行)
  • GUIでTest Planを作り、実行する
  • JMXファイルをCLIで実行する
  • HTMLレポートを確認する

インストール

Javaが必要(JDK 11以上を推奨)。先にバージョンを確認する。

java -version

macOS(Homebrew)

brew install jmeter

インストール後、jmeter コマンドでGUIが起動する。

Linux / Windows

Apache JMeterの公式サイト(https://jmeter.apache.org/download_jmeter.cgi)からzipをダウンロードし、解凍した bin/jmeter(Linux/macOS)または bin/jmeter.bat(Windows)で起動する。

主要コンポーネント

JMeterのTest Planは複数のコンポーネントを積み重ねて作る。

コンポーネント分類役割
Test Planテスト全体のルート。JMXファイル1つが1つのTest Plan
Thread GroupThreads仮想ユーザー数・ループ回数・Ramp-upを設定する
HTTP RequestSampler実際にHTTPリクエストを送る要素
HTTP Request DefaultsConfig ElementThread Group内の全Samplerに共通するホスト・ポートを一括設定する
CounterConfig Elementテストごとに連番を生成する(ユニークなデータを作るときに使う)
HTTP Header ManagerConfig Elementリクエストヘッダー(Content-Type 等)を設定する
Summary ReportListener集計結果をテーブル表示する(CLIでは標準出力に出る)
View Results TreeListenerリクエスト・レスポンスの詳細を1件ずつ確認できる(デバッグ用)
Constant TimerTimer各リクエストの前に一定の待機時間を挟む

Thread Groupの3つの設定

設定名意味
Number of Threads (users)並行して動かす仮想ユーザー数
Ramp-up Period (seconds)全スレッドを起動し終えるまでの秒数。10スレッド / 2秒 なら0.2秒ごとに1スレッドずつ立ち上がる
Loop Count1スレッドが何回ループするか。10スレッド × 10ループ = 100リクエスト

テスト対象サーバーを用意する

JMeterのテストはHTTPを返すサーバーであれば何でもよい。ここではNode.js組み込みの http モジュールだけで動く最小サーバーを使う。

// test-server.js
const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ ok: true, path: req.url }));
});

server.listen(3000, () => {
  console.log('http://localhost:3000 で起動中');
});
node test-server.js

これで http://localhost:3000 がJSONを返すようになる。JMeterを動かす間はこのターミナルを残しておく。

GUIでTest Planを作る

jmeter   # GUIが起動する

手順

① Thread Groupを追加する

左ペインの「Test Plan」を右クリック → Add → Threads (Users) → Thread Group

  • Number of Threads: 10
  • Ramp-up Period: 1
  • Loop Count: 10

→ 10スレッド × 10ループ = 100リクエスト

② HTTP Request Defaultsを追加する(省略可)

「Thread Group」を右クリック → Add → Config Element → HTTP Request Defaults

  • Server Name or IP: localhost
  • Port Number: 3000

これを入れておくと、HTTP Requestサンプラーにホストとポートを毎回書かずに済む。

③ HTTP Requestを追加する

「Thread Group」を右クリック → Add → Sampler → HTTP Request

  • HTTP Request Defaultsを使う場合: Server Name、Port はデフォルトのままでよい
  • Method: GET
  • Path: /

④ Listenerを追加する

「Thread Group」を右クリック → Add → Listener → Summary Report
デバッグ時は同じく → Add → Listener → View Results Tree も追加する

⑤ 保存して実行する

File → Save(test-plan.jmx など任意の名前で保存)
Ctrl + R(またはRun → Start)で実行

View Results Treeで確認できること

実行後、各行をクリックすると詳細を確認できる。

  • 緑 → 成功(2xx)
  • 赤 → 失敗(エラーや 4xx/5xx)
  • 「Request」タブで送ったリクエスト、「Response」タブでレスポンスボディを確認できる

デバッグが終わったら View Results Tree を右クリックして「Disable」にする。全レスポンスをメモリに溜めるため、大量リクエスト時にJMeter自体が重くなる原因になる。

JMXファイルのサンプル

GUIを使わずに手元にJMXファイルを置きたい場合は、次のXMLをそのまま使える。test-plan.jmx などの名前で保存する。

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0">
  <hashTree>
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Sample Test Plan">
      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments">
        <collectionProp name="Arguments.arguments"/>
      </elementProp>
    </TestPlan>
    <hashTree>
      <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group">
        <intProp name="ThreadGroup.num_threads">10</intProp>
        <intProp name="ThreadGroup.ramp_time">1</intProp>
        <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController">
          <boolProp name="LoopController.continue_forever">false</boolProp>
          <intProp name="LoopController.loops">10</intProp>
        </elementProp>
      </ThreadGroup>
      <hashTree>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="GET /">
          <stringProp name="HTTPSampler.domain">localhost</stringProp>
          <intProp name="HTTPSampler.port">3000</intProp>
          <stringProp name="HTTPSampler.path">/</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
        </HTTPSamplerProxy>
        <hashTree/>
        <ResultCollector guiclass="SummaryReport" testclass="ResultCollector" testname="Summary Report">
          <boolProp name="ResultCollector.error_logging">false</boolProp>
          <objProp>
            <name>saveConfig</name>
            <value class="SampleSaveConfiguration">
              <time>true</time>
              <latency>true</latency>
              <timestamp>true</timestamp>
              <success>true</success>
              <label>true</label>
              <code>true</code>
              <message>true</message>
              <threadName>true</threadName>
              <dataType>true</dataType>
              <encoding>false</encoding>
              <assertions>true</assertions>
              <subresults>true</subresults>
              <responseData>false</responseData>
              <samplerData>false</samplerData>
              <xml>false</xml>
              <fieldNames>true</fieldNames>
              <responseHeaders>false</responseHeaders>
              <requestHeaders>false</requestHeaders>
              <responseDataOnError>false</responseDataOnError>
              <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
              <bytes>true</bytes>
              <sentBytes>true</sentBytes>
              <url>true</url>
              <threadCounts>true</threadCounts>
              <idleTime>true</idleTime>
              <connectTime>true</connectTime>
            </value>
          </objProp>
          <stringProp name="filename"></stringProp>
        </ResultCollector>
        <hashTree/>
      </hashTree>
    </hashTree>
  </hashTree>
</jmeterTestPlan>

CLIで実行する

GUIは設定確認に便利だが、CIに組み込んだり繰り返し実行するにはCLIが適している。

# 実行のみ(結果をJTLファイルに出力)
jmeter -n -t test-plan.jmx -l results.jtl

# 実行 + HTMLレポートも同時に生成
jmeter -n -t test-plan.jmx -l results.jtl -e -o ./report
オプション意味
-nnon-GUIモード(CLIで実行)
-t使用するJMXファイルを指定する
-l結果をJTLファイルに書き出す
-eテスト終了後にHTMLレポートを生成する
-oHTMLレポートの出力先ディレクトリ

./report が既に存在するとエラーになる。再実行するときは先に削除する。

rm -rf ./report && jmeter -n -t test-plan.jmx -l results.jtl -e -o ./report

結果の読み方

CLIの標準出力やGUIのSummary Reportに表示されるカラムの意味。

カラム単位意味
# Samples送ったリクエストの総数
Averagems平均レスポンスタイム
Min / Maxms最小 / 最大レスポンスタイム
90th pctms90パーセンタイル(100件中90件がこの時間以内に完了)
Throughputreq/s1秒あたりの処理件数
Received KB/sKB/s受信データ量
Error %%エラーになったリクエストの割合

見るべき指標

Error % が 0 であることをまず確認する。エラーがあれば View Results Tree で原因(ステータスコード・レスポンスボディ)を確認する。

Throughput(req/s) が高いほど処理能力が高い。ただし、ローカルでのループバック接続はネットワーク遅延がほぼ0のため、実際の本番環境とは数値が異なる。「同じ環境での設定変更前後の比較」や「ボトルネックの相対的な特定」に使うイメージが正しい。

90th pct が Average よりはるかに大きい 場合、一部のリクエストだけ極端に遅い(外れ値がある)ことを示す。全体の平均が良くても90th pctが大きければ、一部のユーザーが遅延を体験していることになる。

HTMLレポートを確認する

open ./report/index.html   # macOS

Statistics タブにSummary Reportと同じ集計値が表示される。
Charts タブにレスポンスタイムの時系列グラフが表示される。スループットが途中から落ちている、レスポンスタイムが後半に悪化しているといった傾向を視覚的に確認しやすい。

実装チェックリスト

  • JDKのバージョンを確認する(11以上)
  • JMeterをインストールし jmeter コマンドでGUI起動を確認する
  • test-server.js を起動してレスポンスを確認する
  • GUIでTest Plan(Thread Group + HTTP Request + Summary Report)を作成する
  • GUIで実行し、Summary Report の Error % が 0 になることを確認する
  • JMXファイルを保存してCLIで実行する(-n -t -l -e -o オプション)
  • ./report/index.html でHTMLレポートを確認する

参考