Page tree
Skip to end of metadata
Go to start of metadata

概要

CIツールのJenkinsと負荷試験等で使用されるJMeterを使って、
性能試験レポートとグラフチャートを生成するシステムを構築します。


検証環境:

  • OS

    CentOS 6.6にて検証を行いました。
    本検証環境はミニマムインストールを行ったOSを使用しています。


全体図

 

構築手順

この手順では、Apache、PHP、Jenkins、ant、JMeterは全て同一のサーバにてインストールすることを想定した手順となっています。
インストールするサーバが違う場合は、手順の一部を変更する必要があります。

 

  1. Webサーバ構築

    yum install httpd php

    ApacheとPHPは適宜環境に合わせて構築してください。

    1. 実験用PHPファイルの設置

      index.php
      <?php
          echo 'Hello ' . htmlspecialchars($_GET["name"]) . '!';
      ?>

      ドキュメントルートに上記のindex.phpファイルを設置してください。



  2. Jenkinsのインストール

     Click here to expand...

    このページの内容:

    検証環境:

    • OS

      CentOS 5.6にて検証を行いました。
      本検証環境はミニマムインストールを行ったOSを使用しています。


     依存関係

    • java

      yum install java

     インストールに必要なツール

    • 特になし

    Jenkinsのインストール手順

    • Jenkinsリポジトリ

      # リポジトリ情報を記載する
      wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
       
      # GPG Keyのインストール
      rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key

       

       

    • Jenkinsのインストール手順手順を記載しております。

      # インストール
      yum install jenkins
       
      # Jenkins起動
      /etc/init.d/jenkins start

       

       

     環境変数の設定

     特になし



  3. JMeterのインストール

     Click here to expand...

    このページの内容:


    検証環境:

    • OS

      CentOS 6.6にて検証を行いました。
      本検証環境はミニマムインストールを行ったOSを使用しています。


    依存関係

    下記のミドルウェアを事前にインストールする必要があります。

    • java

      yum install java

       

       

    インストールに必要なツール

    • wget(CentOS6.xのミニマムインストールではインストールされないため)

      yum install wget

    JMeter version 2.13のインストール手順

    • JMeter version 2.13のインストール手順を記載しております。

      # 作業ディレクトリの作成
      mkdir -p /usr/local/src/jmeter
       
      # 作業ディレクトリに移動
      cd /usr/local/src/jmeter
       
      # JMeter version 2.13ダウンロード
      wget https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-2.13.tgz
       
      # ダウンロードしたデータを解凍
      tar xvzf apache-jmeter-2.13.tgz
       
      # 解凍先へ移動
      cd apache-jmeter-2.13
       
      # /binの下にjmaterコマンドのシンボリックリンクを設置する
      ln -s /usr/local/src/jmeter/apache-jmeter-2.13/bin/jmeter /bin/jmeter
      

       



    • 動作確認
      1. phpプログラムをドキュメントルートに設置(Apache+PHPなどの環境を準備)

        index.php
        <?php
            echo 'Hello ' . htmlspecialchars($_GET["name"]) . '!';
        ?>



      2. 実行確認用サンプルJMaterシナリオを設置(sample.jmx)

         Click here to expand...
        sample.jmx
        <?xml version="1.0" encoding="UTF-8"?>
        <jmeterTestPlan version="1.2" properties="2.8" jmeter="2.13 r1665067">
          <hashTree>
            <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="テスト計画" enabled="true">
              <stringProp name="TestPlan.comments"></stringProp>
              <boolProp name="TestPlan.functional_mode">false</boolProp>
              <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
              <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="ユーザー定義変数" enabled="true">
                <collectionProp name="Arguments.arguments"/>
              </elementProp>
              <stringProp name="TestPlan.user_define_classpath"></stringProp>
            </TestPlan>
            <hashTree>
              <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="スレッドグループ" enabled="true">
                <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
                <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="ループコントローラ" enabled="true">
                  <boolProp name="LoopController.continue_forever">false</boolProp>
                  <stringProp name="LoopController.loops">${__P(loop)}</stringProp>
                </elementProp>
                <stringProp name="ThreadGroup.num_threads">${__P(thread)}</stringProp>
                <stringProp name="ThreadGroup.ramp_time">${__P(rampup)}</stringProp>
                <longProp name="ThreadGroup.start_time">1443495709000</longProp>
                <longProp name="ThreadGroup.end_time">1443495709000</longProp>
                <boolProp name="ThreadGroup.scheduler">false</boolProp>
                <stringProp name="ThreadGroup.duration"></stringProp>
                <stringProp name="ThreadGroup.delay"></stringProp>
              </ThreadGroup>
              <hashTree>
                <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP リクエスト初期値設定" enabled="true">
                  <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="ユーザー定義変数" enabled="true">
                    <collectionProp name="Arguments.arguments"/>
                  </elementProp>
                  <stringProp name="HTTPSampler.domain">${__P(host)}</stringProp>
                  <stringProp name="HTTPSampler.port">${port}</stringProp>
                  <stringProp name="HTTPSampler.connect_timeout"></stringProp>
                  <stringProp name="HTTPSampler.response_timeout"></stringProp>
                  <stringProp name="HTTPSampler.protocol"></stringProp>
                  <stringProp name="HTTPSampler.contentEncoding"></stringProp>
                  <stringProp name="HTTPSampler.path"></stringProp>
                  <stringProp name="HTTPSampler.concurrentPool">4</stringProp>
                </ConfigTestElement>
                <hashTree/>
                <ResultCollector guiclass="StatVisualizer" testclass="ResultCollector" testname="統計レポート" enabled="true">
                  <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>false</fieldNames>
                      <responseHeaders>false</responseHeaders>
                      <requestHeaders>false</requestHeaders>
                      <responseDataOnError>false</responseDataOnError>
                      <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
                      <assertionsResultsToSave>0</assertionsResultsToSave>
                      <bytes>true</bytes>
                      <threadCounts>true</threadCounts>
                    </value>
                  </objProp>
                  <stringProp name="filename"></stringProp>
                </ResultCollector>
                <hashTree/>
                <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP リクエスト" enabled="true">
                  <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="ユーザー定義変数" enabled="true">
                    <collectionProp name="Arguments.arguments"/>
                  </elementProp>
                  <stringProp name="HTTPSampler.domain"></stringProp>
                  <stringProp name="HTTPSampler.port"></stringProp>
                  <stringProp name="HTTPSampler.connect_timeout"></stringProp>
                  <stringProp name="HTTPSampler.response_timeout"></stringProp>
                  <stringProp name="HTTPSampler.protocol"></stringProp>
                  <stringProp name="HTTPSampler.contentEncoding"></stringProp>
                  <stringProp name="HTTPSampler.path">/index.php?name=test</stringProp>
                  <stringProp name="HTTPSampler.method">GET</stringProp>
                  <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
                  <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
                  <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
                  <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
                  <boolProp name="HTTPSampler.monitor">false</boolProp>
                  <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
                </HTTPSamplerProxy>
                <hashTree/>
              </hashTree>
            </hashTree>
          </hashTree>
        </jmeterTestPlan>
        
        



      3. JMaterの実行

        jmeter -n -t sample.jmx -Jhost=localhost -Jthread=[並列でリクエストを発行するスレッド数] -Jrampup=[threadの立ち上がりに使用する時間(秒)] -Jloop=[試行回数] -l [ログファイル]

        [root@localhost apache-jmeter-2.13]# jmeter -n -t sample.jmx -Jhost=localhost -Jthread=1 -Jrampup=1 -Jloop=1 -l ./test.log
        Creating summariser <summary>
        Created the tree successfully using sample.jmx
        Starting the test @ Tue Sep 29 23:25:15 JST 2015 (1443536715897)
        Waiting for possible shutdown message on port 4445
        summary =      1 in   0.3s =    3.0/s Avg:    40 Min:    40 Max:    40 Err:     0 (0.00%)
        Tidying up ...    @ Tue Sep 29 23:25:16 JST 2015 (1443536716314)
        ... end of run

     環境変数の設定

     特になし



  4. antなどのJenkinsとJMeterの実行に必要なソフトウェアをインストール

    yum install ant ant-trax junit



  5. Jenkisでのパフォーマンスプラグインの導入(Jenkins管理画面の操作「ブラウザ」)
    1. JenkinsのWeb管理画面にログインします。


    2. Jenkinsの管理へ移動します。


      1. 「Jenkinsの管理」というリンクをクリックします。

    3. プラグインの管理へ移動

       

      1. プラグインの管理をクリックします。

    4. 高度な設定からプラグインをアップロード

      1. 図の①「高度な設定」をクリックします。
      2. 図の②の参照をクリックし、パフォーマンスプラグインをアップロードします。

        1. パフォーマンスプラグインはバージョン1.9で検証しております。

          パフォーマンスプラグインの入手

          プラグインTOPページ
           https://wiki.jenkins-ci.org/display/JENKINS/Performance+Plugin


          バージョン1.9ダウンロードURL

           http://updates.jenkins-ci.org/download/plugins/performance/1.9/performance.hpi
           最新版1.13を使用するとグラフ・メニュー表示に問題が有ったため、異常がなかった1.9を利用しております。
           また、古いバージョンを指定してインストールするため、高度な設定からインストールしています。
      3. アップロードをクリックします。

    5. インストール確認画面


      1. インストール完了後、ジョブがなければJenkinsを再起動するをチェックし、インストール完了を待ちます。

    6. 再起動画面


      1. 再起動中になると上記の画面になります。準備が完了するとブラウザがリロードされますが、リロードされない場合は手動でリロードしてください。

  6. Jenkisにてジョブの作成
    1. TOPページ


      1. TOPページから「新規ジョブ作成」をクリックします。

    2. ジョブの初期設定


      1. 図の①にジョブ名を入力します。ここでは、仮として「jmeter」という名前にしております。
      2. 図の②の「フリースタイル・プロジェクトのビルド」を選択します。
      3. 設定が完了したら、図の③の「OK」ボタンをクリックします。

    3. ビルドの設定


      1. プロジェクト設定画面にて、ビルドの手順を追加します。
        ビルドは「Ant呼び出し」を選択します。

    4. Antの高度な設定


      1. 高度な設定をクリックします。

    5. Antの高度な設定を追加


      1. 図の①ビルドファイルに「build.xml」と記述します。
      2. 図の②Javaオプションに「-Djmeter-home=/usr/local/src/jmater/apache-jmeter-2.13/ -Dtarget-host=localhost -Dthread=20 -Drampup=1 -Dloop=3」と記述します。

        Javaオプションはbuild.xmlに記載した変数に基づいて設定します。
        本手順とは違うbuild.xmlを使用する場合は、適宜修正してください。



    6. ビルド後の処理の追加


      1. プロジェクト設定画面にて、「ビルド後の処理の追加」を選択し、
        「Publish Performance test result report」を選択します。

    7. Publish Performance test result reportの設定(レポートの追加)


      1. 「Add a new report」をクリックし、JMeterを選択します。

    8. Publish Performance test result reportの設定(読み込むレポートファイルの選択)


      1. Report filesに「**/*.jtl」と記述します。

        build.xmlに記載したレポート出力先に依存します。
        build.xmlを修正した場合は、適宜修正が必要になります。



    9. プロジェクトの設定を保存


      1. 図の保存ボタンを押すことで、プロジェクト設定が保存されます。

  7. 「build.xml」と「sample.jmx」の設置(サーバのコンソールから操作します)
    1. 手順

      # ジョブ「jmeter」のデータディレクトリに移動
      ## 作成したジョブ名に合わせて適宜変更してください
      cd /var/lib/jenkins/jobs/jmeter
      
      # ワークスペースを作成
      mkdir workspace
      
      # ジョブ「jmeter」のワークスペースへ移動
      cd /var/lib/jenkins/jobs/jmeter/workspace
      
      # antのビルドファイル(build.xml)を作成します。
      vi build.xml
      
      # シナリオファイル格納ディレクトリの作成
      mkdir -p  test/jmeter
      
      # JMeterシナリオファイル(sample.jmx)を作成します。
      vi test/jmeter/sample.jmx
      
      # Jenkinsがワークスペースを制御できるように「/var/lib/jenkins/jobs/jmeter/workspace」の権限を変更
      chown -R jenkins:jenkins /var/lib/jenkins/jobs/jmeter/workspace



    2. build.xml

      build.xml
      <project default="all"><!-- 実行タスクのdefaultをallに指定 -->
        <!-- antプログラムの指定 -->
        <path id="ant.jmeter.classpath">
          <fileset dir="${jmeter-home}/extras/">
            <include name="ant-jmeter*.jar"/>
          </fileset>
        </path>
        
        <!-- プロパティ設定 -->
        <property name="resulet-filename" value="loadtest"/>
        
        <!-- antタスクの定義 -->
        <taskdef
          name="jmeter"
          classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask"
          classpathref="ant.jmeter.classpath" />
          
        <!-- タスクallの定義 -->
        <target name="all" depends="clean,run,report"/>
        
        <!-- タスクcleanの定義 -->
        <target name="clean">
          <delete dir="results"/>
          <delete file="jmeter.log"/>
          <mkdir dir="results/jtl"/>
          <mkdir dir="results/html"/>
        </target>
        
        <!-- タスクrunの定義 -->
        <target name="run" depends="clean">
          <!-- JMeterの初期設定 -->
          <jmeter
             jmeterhome="${jmeter-home}"
             resultlogdir="results/jtl"
             resultlog="${resulet-filename}.jtl">
          <!--
            <jvmarg value="-Xincgc"/>
            <jvmarg value="-Xmx128m"/>
            <jvmarg value="-Dproperty=value"/>
            <jmeterarg value="-qextra.properties"/>
          -->
          
            <testplans dir="test/jmeter" includes="*.jmx"/>
            <property name="jmeter.save.saveservice.output_format" value="xml"/>
            <property name="jmeter.save.saveservice.assertion_results" value="all"/>
            <property name="jmeter.save.saveservice.bytes" value="true"/>
            
            <!-- JMeterのシナリオの変数の定義 -->
            <property name="host" value="${target-host}"/>
            <property name="thread" value="${thread}"/>
            <property name="rampup" value="${rampup}"/>
            <property name="loop" value="${loop}"/>
          </jmeter>
        </target>
        
        <!-- タスクreportの定義 -->
        <target name="report" depends="run">
          <xslt
             basedir="results/jtl"
             destdir="results/html"
             includes="*.jtl"
             style="${jmeter-home}/extras/jmeter-results-detail-report_21.xsl"/>
        </target>
      </project>

       

       

    3. sample.jmx

      sample.jmx
      <?xml version="1.0" encoding="UTF-8"?>
      <jmeterTestPlan version="1.2" properties="2.8" jmeter="2.13 r1665067">
        <hashTree>
          <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="テスト計画" enabled="true">
            <stringProp name="TestPlan.comments"></stringProp>
            <boolProp name="TestPlan.functional_mode">false</boolProp>
            <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
            <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="ユーザー定義変数" enabled="true">
              <collectionProp name="Arguments.arguments"/>
            </elementProp>
            <stringProp name="TestPlan.user_define_classpath"></stringProp>
          </TestPlan>
          <hashTree>
            <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname=" スレッドグループ" enabled="true">
              <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
              <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="ループコントローラ" enabled="true">
                <boolProp name="LoopController.continue_forever">false</boolProp>
                <stringProp name="LoopController.loops">${__P(loop)}</stringProp>
              </elementProp>
              <stringProp name="ThreadGroup.num_threads">${__P(thread)}</stringProp>
              <stringProp name="ThreadGroup.ramp_time">${__P(rampup)}</stringProp>
              <longProp name="ThreadGroup.start_time">1443495709000</longProp>
              <longProp name="ThreadGroup.end_time">1443495709000</longProp>
              <boolProp name="ThreadGroup.scheduler">false</boolProp>
              <stringProp name="ThreadGroup.duration"></stringProp>
              <stringProp name="ThreadGroup.delay"></stringProp>
            </ThreadGroup>
            <hashTree>
              <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP リクエスト初期値設定" enabled="true">
                <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="ユーザー定義変数" enabled="true">
                  <collectionProp name="Arguments.arguments"/>
                </elementProp>
                <stringProp name="HTTPSampler.domain">${__P(host)}</stringProp>
                <stringProp name="HTTPSampler.port">${port}</stringProp>
                <stringProp name="HTTPSampler.connect_timeout"></stringProp>
                <stringProp name="HTTPSampler.response_timeout"></stringProp>
                <stringProp name="HTTPSampler.protocol"></stringProp>
                <stringProp name="HTTPSampler.contentEncoding"></stringProp>
                <stringProp name="HTTPSampler.path"></stringProp>
                <stringProp name="HTTPSampler.concurrentPool">4</stringProp>
              </ConfigTestElement>
              <hashTree/>
              <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP リクエスト" enabled="true">
                <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="ユーザー定義変数" enabled="true">
                  <collectionProp name="Arguments.arguments"/>
                </elementProp>
                <stringProp name="HTTPSampler.domain"></stringProp>
                <stringProp name="HTTPSampler.port"></stringProp>
                <stringProp name="HTTPSampler.connect_timeout"></stringProp>
                <stringProp name="HTTPSampler.response_timeout"></stringProp>
                <stringProp name="HTTPSampler.protocol"></stringProp>
                <stringProp name="HTTPSampler.contentEncoding"></stringProp>
                <stringProp name="HTTPSampler.path">/index.php?name=test</stringProp>
                <stringProp name="HTTPSampler.method">GET</stringProp>
                <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
                <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
                <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
                <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
                <boolProp name="HTTPSampler.monitor">false</boolProp>
                <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
              </HTTPSamplerProxy>
              <hashTree/>
              <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP リクエスト" enabled="true">
                <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="ユーザー定義変数" enabled="true">
                  <collectionProp name="Arguments.arguments"/>
                </elementProp>
                <stringProp name="HTTPSampler.domain"></stringProp>
                <stringProp name="HTTPSampler.port"></stringProp>
                <stringProp name="HTTPSampler.connect_timeout"></stringProp>
                <stringProp name="HTTPSampler.response_timeout"></stringProp>
                <stringProp name="HTTPSampler.protocol"></stringProp>
                <stringProp name="HTTPSampler.contentEncoding"></stringProp>
                <stringProp name="HTTPSampler.path">/index.php?name=world!</stringProp>
                <stringProp name="HTTPSampler.method">GET</stringProp>
                <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
                <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
                <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
                <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
                <boolProp name="HTTPSampler.monitor">false</boolProp>
                <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
              </HTTPSamplerProxy>
              <hashTree/>
            </hashTree>
          </hashTree>
        </hashTree>
      </jmeterTestPlan>

       



  8. ビルドの実行(Jenkins管理画面の操作「ブラウザ」)
    1. プロジェクトの選択


      1. プロジェクトを選択します。
        今回は、「jmeter」プロジェクトのリンクをクリックします。

    2. ビルドの実行


      1. 図の「ビルド実行」をクリックします。

    3. 完了したビルドの実行結果確認


      1. 図の「#1」をクリックし、ビルド結果を確認します。
        1. この時、青い画像であれば成功です。赤い画像であった場合は、何かビルド上で問題が発生している可能性があります。

    4. Performance Reportの確認


      1. Performance Reportを確認するために、ビルド結果画面の「Performance Report」をクリックします。

    5. Performance Report


      1. 「Performance Report」は上記の様な表示になります。
        1. グラフは表示されておりませんが、二回目以降のジョブを実行することで始めてグラフが表示されます。

  9. 2回めのジョブ実行完了後の画面
    1. プロジェクトトップ


    2. ジョブ毎の「Performance Report」

 

 

  • No labels
Write a comment…