wancoro blog

学んだことをアウトプットしていきたいと思います

Jenkins Pipelineで Performance Pluginを使ってみる

はじめに

Jenkins初心者な自分がパイプラインを書くことになったので、
Performance Pluginを使う場合の書き方、Jenkins操作方法を記します。
JMeterでのjmxファイルの作成方法は記しません。

Performance Pluginを使用するに至った経緯

今回はJenkinsからJMeterを実行し、出力レポートを過去の結果と比較するため
Performance Pluginを使うことになりました。

環境情報

事前準備

  • jmxファイルを用意する
  • Jenkinsのダッシュボードを用意する

Jenkinsfile書き方

pipeline {
    agent any // 無いと怒られた
    stages {
        stage('Performance Test') {
            steps {
                bzt 'jmeter-example.jmx'  // 実行するjmxのファイルパスを指定
            }
        }
​
        stage('Report') {
            steps {
                perfReport '**/*.jtl' // 出力するレポートの形式を指定
            }
        }
    }
}

stepの詳細は以下ドキュメントを参照してください。

www.jenkins.io

Pipeline実行方法

Piplelineジョブの作成

今回はJenkinsのGUIからパイプラインのジョブを作成します。 f:id:wancoromochi:20210108095507p:plain 新規ジョブ作成→ジョブに名前をつける→パイプラインを選択→OKを押下

f:id:wancoromochi:20210108095711p:plain パイプラインタブを選択→スクリプトを貼付→保存を押下

作成したジョブを実行

f:id:wancoromochi:20210108095927p:plain Build nowを押下

f:id:wancoromochi:20210108100204p:plain ビルドが成功すると、Performance Trendから実行結果のグラフが確認できます。

参考情報

Performance Pluginのインストール方法はこちらを参考にさせていただきました。 blue-38.hatenablog.com

has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Aサーバで呼び出したJavascriptからBサーバのHTMLファイルを呼び出ししようとすると、エラーが出た

*** has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

CORSとは?

ajax通信をするために、安全性を保つため、
リソースの取得先をアプリケーション呼び出し元と同一のオリジン(ドメインのこと?)に限定するらしい。
それ以外のオリジンから取得したい場合はCORSの設定がいるとのこと。

developer.mozilla.org

対処方法

レスポンスを返却する側のヘッダーに以下を追加する

Access-Control-Allow-Origin: <origin-url>

developer.mozilla.org

DockerにSSHできなかった問題を解決した話

事象

[Docker入門]コンテナにsshでアクセスするための設定メモ - Qiita
上記ドキュメント通りにdockerを起動しても、ホストからSSH接続ができない。
途中でConnection reset by peerとエラーが出てしまう。

別の事象

docker build時に、apt実行に失敗しtemporary failure resolvingとエラーが出ていた。 解消するために、--network=hostオプションをつけていた。

解決策

ダメもとで以下ドキュメントのDockerデーモンのオプションに「--dns」を指定するを試してみたら、SSHできるようになった。
docker image build時に、DNSの設定をなんとかしたい - CLOVER🍀

【Java】No qualifying bean of type 'xxx' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations

テストを実行するとエラー

No qualifying bean of type 'xxx' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations

beanが読み込まれていないみたい?
web.xmlコンポーネント追記し忘れていたので追加して解決。

<context:base-package="xxx" />

【MySQL】ユニークキー制約はついてないけど重複させたくない時にやったこと

実装環境

やりたいこと

ユーザ作成APIが同時に実行された際に、同じnameのユーザを登録させたくない。
以下のような userテーブルがあり、nameにはユニークキー 制約はついていない。

CREATE TABLE `user` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(255) NOT NULL,
 `age` int(11) NOT NULL,
 PRIMARY KEY (`id`)
);

試したこと

2つのトランザクション内で同じクエリを発行し、動作を確認する。
1. SELECT FOR UPDATE を使う。

BEGIN;

SELECT * FROM user WHERE name='test' FOR UPDATE;

INSERT INTO user( name, age ) VALUES ( 'test', 20 );

COMMIT;

この方法だと、トランザクション1で INSERT 後、トランザクション2で INSERTするとデッドロックが発生してしまった。
デッドロック発生によりロールバックすることで、同じnameのユーザレコードは重複しないという条件は満たせるが、デッドロックはあまりよろしくない。
2. NOT EXSITS を使う。

BEGIN;

INSERT INTO user( name, age ) 
SELECT 'test', 20
WHERE NOT EXISTS( SELECT * FROM user WHERE name='test' );

COMMIT;

この方法だとトランザクション1で INSERT 後、トランザクション2で INSERTしても、1がcommitされるまで2のクエリは実行されない。
サブクエリでSELECTをつけることにより、テーブルロック(インテンションロック)がかかっている様子。

結論

今回の場合は NOT EXISTS でうまくいった。
ユニークキー制約をつければ、こんな複雑なクエリを実装する必要はないので、
可能であればユニークキー制約をつけ、deplicatedError が発生したらロールバックするような挙動が望ましい。

7/16 追記

MySQL5.5の場合

なんとMySQL5.5で実装する必要があった。 MySQL5.5の場合、上記のNOT EXISTS 文ではsyntaxエラーが出てしまい使えない。 というわけで再度調べた。

BEGIN;

INSERT INTO user(name, age) 
SELECT name, age FROM (SELECT 'test' AS name, 20 AS age ) AS u 
WHERE NOT EXISTS ( SELECT * FROM user WHERE name='test' );

COMMIT;

上記のSQLで成功。

MySQL5.5の場合、FROMをつけて値を取得する場所を明示的に指定する必要があるようだ。
サブクエリにはaliasをつけないと怒られるので、
特に使用していないがAS uFROMの後につけている。

参考:

stackoverflow.com

【NGINX】phusion/passenger-dockerでレスポンスヘッダーを編集する

やりたいこと

HTTPのレスポンスヘッダーにnginxなどのバージョン情報を表示させないようにしたい。
調べるとwget でnginxを取得して展開するような記述が多いが、 今回はdockerイメージに phusion/passenger を使用しており、 イメージ内にnginxが含まれているため、別の方法で実装したい。

実行環境

  • docker
  • phusion/passenger-ruby26
  • nginx 1.14.0

修正前のレスポンスヘッダー

< status: 302 Found
< cache-control: no-cache
...
< x-powered-by: Phusion Passenger 6.0.4 *
< server: nginx/1.14.0 + Phusion Passenger 6.0.4 *

*のついたやつを消したい。

実装方法

  • nginxのモジュールをインストールする。
# Dockerfile
RUN apt-get update \
    && apt-get install -y \
        libnginx-mod-http-headers-more-filter \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
  • 設定ファイルを作成する。
# headers_filter.conf
server_tokens off;
more_clear_headers 'Server' 'X-Powered-By';

server_tokens off: nginxのバージョンを削除
more_clear_headers: 指定した行を削除

  • 設定ファイルをDockerの/etc/nginx/conf.d配下に配置する
ADD ./headers_filter.conf /etc/nginx/conf.d/headers_filter.conf

/etc/nginx/main.d とかもありますが、conf.d でないと動かなかったので、こちらに置いてください。

めちゃめちゃ詰まりましたが、これだけでOK。

そのほか

  • more-clear_header を複数行に分けて書くと動かなかった。
# headers_filter.conf
server_tokens off;
more_clear_headers 'Server';
more_clear_headers 'X-Powered-By';
  • nginx-plus-module-headers-more というモジュールは商用nginxでしか使えないらしい。