LoginSignup
3
3

More than 5 years have passed since last update.

Commons HttpClient を使用してネットワーク転送量をキャプチャする

Posted at

動機

ネットワーク転送量をキャプチャしたいときってあるよね。
そんなとき、Commons HttpClient なら可能です。

概要

ネットワーク転送量は、HttpConnection インスタンスのgetMetrics() メソッドで取得できるHttpConnectionMetrics インスタンスに記録されています。

HttpConnection インスタンスは、HttpContext インスタンスのgetAttribute(ExecutionContext.HTTP_CONNECTION)で取得できます。

HttpContext インスタンスを取得するには、HttpRequestInterceptor インターフェースとHttpResponseInterceptor インターフェースを実装したクラスを、addRequestInterceptor() メソッドとaddResponseInterceptor() メソッドを使用してHttpClient(正確には AbstractHttpClient) インスタンスに登録してやります。

実装例

下にHttpRequestInterceptor インターフェースとHttpResponseInterceptorインターフェースの実装を示します。

HttpRequestInterceptorとHttpResponseInterceptorの実装例
class InterceptorImpl implements HttpRequestInterceptor, HttpResponseInterceptor {
    private static final Logger LOG = LoggerFactory.getLogger(InterceptorImpl.class);
    private ThreadLocal<HttpConnectionMetrics> threadLocalMetrics = new ThreadLocal<HttpConnectionMetrics>();

    @Override
    public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
        // context インスタンスから、HttpConnection インスタンスを取得
        final HttpConnection connection = (HttpConnection)context.getAttribute(ExecutionContext.HTTP_CONNECTION);
        // HttpConnection インスタンスからHttpConnectionMetricsを取得
        final HttpConnectionMetrics metrics = connection.getMetrics();
        // サーバにアクセスする前のメトリックをスレッドローカルに保存
        threadLocalMetrics.set(new HttpConnectionMetrics() {
            private final long requestCount = metrics.getRequestCount();
            private final long responseCount = metrics.getResponseCount();
            private final long sentBytesCount = metrics.getSentBytesCount();
            private final long receivedBytesCount = metrics.getReceivedBytesCount();

            @Override
            public long getRequestCount() {
                return this.requestCount;
            }

            @Override
            public long getResponseCount() {
                return responseCount;
            }

            @Override
            public long getSentBytesCount() {
                return sentBytesCount;
            }

            @Override
            public long getReceivedBytesCount() {
                return receivedBytesCount;
            }

            @Override
            public Object getMetric(String metricName) {
                return null;
            }

            @Override
            public void reset() {
            }
        });
    }

    @Override
    public void process(HttpResponse response, HttpContext context) throws HttpException, IOException {
        // context インスタンスから、HttpConnection インスタンスを取得
        final HttpConnection connection = (HttpConnection)context.getAttribute(ExecutionContext.HTTP_CONNECTION);
        // HttpConnection インスタンスからHttpConnectionMetricsを取得
        final HttpConnectionMetrics postMetrics = connection.getMetrics();
        // サーバにアクセスする前のメトリックを取得
        final HttpConnectionMetrics prevMetrics = threadLocalMetrics.get();
        threadLocalMetrics.remove();

        // リクエスト回数
        final long requestCount = postMetrics.getRequestCount() - prevMetrics.getRequestCount();
        // レスポンス回数
        final long responseCount = postMetrics.getResponseCount() - prevMetrics.getResponseCount();
        // 送信バイト数
        final long sentBytesCount = postMetrics.getSentBytesCount() - prevMetrics.getSentBytesCount();
        // 受信バイト数
        final long receivedBytesCount = postMetrics.getReceivedBytesCount() - prevMetrics.getReceivedBytesCount();

        // ログに出力
        LOG.info("requestCount={}, responseCount={}, sentBytesCount={}, receivedBytesCount={}",
                totalRequestCount.get(), totalResponseCount.get(), totalSentBytesCount.get(),
                totalReceivedBytesCount.get());
    }
}

InterceptorImpl クラスは次のようにして使用します。

使用例
public static void main() {
    // タイムアウトを設定してやる
    HttpParams httpParams = new BasicHttpParams();
    HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
    HttpConnectionParams.setSoTimeout(httpParams, 30000);

    // HttpClient インスタンス作成
    SystemDefaultHttpClient httpClient = new SystemDefaultHttpClient(httpParams);
    // Interceptor の登録
    Interceptor interceptor = new Interceptor();
    httpClient.addRequestInterceptor(interceptor);
    httpClient.addResponseInterceptor(interceptor);

    // サーバにアクセス
    HttpGet request = new HttpGet("http://www.yahoo.co.jp/");
    httpClient.exeucte(request);
}

プログラム実行後、ログに出力された値を Excel で集計すれば総量や平均が求まります。
InterceptorImpl から出力されるログを別ファイルにしておけば集計しやすいでしょう。

本実装例は Commons HttpClient 4.2 で確認しています。4.3 でも Deprecation の警告がでますがいけるはず。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3