2012-06-24 8 views
12

Jerseyクライアントを使用して大きなファイルをInputStreamとして配置すると、ファイルの内容全体がメモリにバッファリングされてサーバに送信されているように見えます。このため、JVMのヒープ領域が不足するため、大きなファイルで問題が発生します。 Jerseyクライアントでこの動作を防止するにはどうすればよいですか?サーバー側のJAX-RSリソース・メソッドは、データを送信するときにこの問題がないようです。例えば大きなファイルを投稿するときにJerseyクライアントがメモリ不足エラーを発生するのを防ぐ

WebResource dataUploadResource = buildDataUploadResource(); 
dataUploadResource.type(getMimeType()).put(getLargeInputStream()); 

答えて

13

あなたが要求のためにチャンクエンコーディング1を使用するためにジャージーのクライアントを設定する必要があります。この動作を防止するために。これにより、Content-Lengthヘッダを設定する必要がなくなり、メモリ内の内容全体をバッファリングすることなく、指定されたInputStreamからストリームされます。

デフォルトでJerseyはJDKのHttpURLConectionクラスを使用して、HTTP要求と応答を処理します。残念ながら、これにはチャンクエンコード転送に関するいくつかのバグがあります。幸い、Jerseyには、異なるHTTPクライアント実装を使用できるようにする拡張ポイントがあります。このような実装の1つは、Apache Http Client 2に基づいています。

apache htppクライアントハンドラの2つの実装が存在します.1つは現在のend of life 3.xバージョンをサポートし、もう1つは新しい4.xバージョンを使用します。私たちのプロジェクトでは、古い(3.1)バージョンに基づいて実装を使用しました。ライブラリはMaven Centralの 'contribs'サブグループの下にあります。次はあなたが新しい実装を使用するためにあなたのジャージーのクライアントを初期化する必要が

<dependency> 
    <groupId>com.sun.jersey.contribs</groupId> 
    <artifactId>jersey-apache-client</artifactId> 
    <version>1.14</version> 
</dependency> 

:チャンクエンコーディングを有効にするためには

Client jerseyClient = ApacheHttpClient.create(getClientConfig()); 

を、あなたは、クライアントの構成にチャンクエンコーディングのサイズを設定する必要がありますこれはデフォルトで有効になっていない:

private ClientConfig getClientConfig() { 
    ClientConfig config = new DefaultClientConfig(); 

    config.getProperties().put(
      DefaultApacheHttpClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE, 0); 
    return config; 
} 

は限り、このプロパティはnullないよう、エンコーディングが使用されますチャンク。実際、バージョン1.14では、基本となるapache commons-httpclientライブラリではサイズが指定されていないため、エンコーディングサイズは無視されます。

+1

残念ながら、これは信頼性をもって動作しているようには見えません。そのため、Jerseyコードでは、デフォルトでエンコードされたエンコードがチャンク化されています。 HttpURLConnectionにはいくつかのリクエストが奇妙なやり方で失敗し、セミランダム(テストのサブセットが失敗します。失敗したテストだけを再実行すると、それらの小さなサブセットが失敗します。より小さなサブセットであっても失敗し、最終的にすべてが合格)。ですから、真剣な作業のために、より堅牢なクライアントコネクタを使用することをお勧めします。 –

+1

ご意見ありがとうございます。 Apache Httpクライアントコネクタを使用してチャンクエンコードを使用するようにクライアントを設定する方法を示す答えを更新しました。 – Eric

関連する問題