これは何?
- 少数(1〜数台)のクライアント環境から多数のWebアクセスのエミュレート及びそのレスポンスを計測する際に活用するコード。
- 指定のURLにGETリクエストを送出し、そのレスポンス(ボディ)データと処理時間(リクエスト送出からレスポンス受信まで)を算出。
※一般のブラウザのようにレスポンス取得からデータの描画までの処理時間は含まれない。 - main()内でスレッドプール(Webクライアント数)とタスク(合計アクセス数)を生成。仮にクライアントが応答無しになった場合は、最大awaitTime秒待って強制終了する。
- このツールを使用した際の評価の書き方としては「XクライアントからのY時間あたりZアクセス数が発生した時のAAA(サーバ負荷|クライアントのレスポンス時間[最大|平均|最小])」の用になる見込みだが、Yを計測するコードは入れていない。。。(若干わかりにくいので、もっと簡潔な表現に落とす必要があるかも)
- URLの指定はコマンドラインパラメータからできるように修正した方が良かったが、時間の関係で割愛している。(URLの修正にいちいち再コンパイルは手間ではある)
使い方は?
- 下記のソースをJavaでコンパイルし、java Mainコマンドで実行する。(Eclipseがあればそれを使用すると手間が省ける)
- アクセスURLとパラメータには気をつけること(外部サイトを指定してDOS攻撃に間違えられないように、自分のサーバか、localサーバなどを使用すること)
- 現状実行結果を標準出力している。スレッドセーフな整形ログ出力を追加で書き込むのも良いし、標準出力内容を簡易的にして、プログラムの実行結果をファイルにリダイレクトするのも良い。
ソースコード
Main.java
package info.yukun.autoWebAccess; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class Main { public static void main(String[] args) throws InterruptedException { System.out.println("Entering main"); // スレッドの作成数 ExecutorService pool = Executors.newFixedThreadPool(20); // レスポンス計測対象のページ final String url = "http://www.example.com/"; // タスク完了を待つ時間(sec) final long awaitTime = 5 * 60; // スレッドpoolに投げるタスク内容 Runnable task = new Runnable() { public void run() { NetHttpClient http = new NetHttpClient(url); http.executeGet(); System.out.println("Client - " + Thread.currentThread().getId() + ": " + http.getResponseTime() + "sec"); } }; // スレッドプールにタスクを投げる for (int i = 0; i < 50; i++) { pool.execute(task); } try { // 全タスクが終了後にスレッドを終了させる。 pool.shutdown(); // (全てのタスクが終了した場合、trueを返しif内はスキップ) if (!pool.awaitTermination(awaitTime, TimeUnit.SECONDS)) { // タイムアウトした場合、全てのスレッドを中断(interrupted)してスレッドプールを破棄する。 pool.shutdownNow(); } } catch (InterruptedException e) { // awaitTerminationスレッドがinterruptedした場合も、全てのスレッドを中断する System.out.println("awaitTermination interrupted: " + e); pool.shutdownNow(); } System.out.println("Exit main"); } } [/java] <h4>NetHttpClient.java</h4> [java] package info.yukun.autoWebAccess; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; public class NetHttpClient { private StringBuffer res; private long msec; private String path; public NetHttpClient(String url) { this.res = new StringBuffer(); this.path = url; } public void executeGet() { long start = System.currentTimeMillis(); try { URL url = new URL(path); HttpURLConnection connection = null; try { connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { try (InputStreamReader isr = new InputStreamReader( connection.getInputStream(), StandardCharsets.UTF_8); BufferedReader reader = new BufferedReader(isr)) { String line; while ((line = reader.readLine()) != null) { res.append(line); res.append(System.getProperty("line.separator")); } } } } finally { if (connection != null) { connection.disconnect(); } } } catch (IOException e) { e.printStackTrace(); } long stop = System.currentTimeMillis(); msec = stop - start; } public double getResponseTime() { return (double) msec / 1000; } public StringBuffer getResponse() { return res; } }
実行結果 (イメージ)
Entering main Client - 25: 1.896sec Client - 18: 1.946sec Client - 15: 2.155sec Client - 11: 2.424sec Client - 16: 2.525sec Client - 26: 2.643sec Client - 22: 3.652sec Client - 23: 3.667sec Client - 13: 4.007sec Client - 19: 4.074sec Client - 29: 4.105sec Client - 27: 4.349sec Client - 21: 5.917sec Client - 30: 5.935sec Client - 28: 5.946sec Client - 11: 3.583sec Client - 20: 6.029sec Client - 26: 4.085sec Client - 23: 3.467sec Client - 17: 7.298sec Client - 19: 3.426sec Client - 16: 5.457sec Client - 27: 3.652sec Client - 13: 4.02sec Client - 22: 4.463sec Client - 29: 4.258sec Client - 28: 2.899sec Client - 11: 3.539sec Client - 30: 3.627sec Client - 21: 3.731sec Client - 26: 3.103sec Client - 23: 2.702sec Client - 25: 7.986sec Client - 14: 9.971sec Client - 20: 4.612sec Client - 16: 3.385sec Client - 29: 3.05sec Client - 22: 3.415sec Client - 13: 3.535sec Client - 28: 2.95sec Client - 30: 2.692sec Client - 27: 4.542sec Client - 19: 5.435sec Client - 17: 5.652sec Client - 11: 3.582sec Client - 21: 3.484sec Client - 24: 13.501sec Client - 12: 13.605sec Client - 15: 11.518sec Client - 18: 11.781sec Exit main