REST URLを呼び出して、応答を返すのにかかる時間を測定しようとしています。
REST URL
から応答を取得するために、DefaultHttpClient
を使用しています。
以下のプログラムでは、各スレッドは特定の範囲で動作します。各スレッドが1 - 100
間で機能し、2番目のスレッドが101 - 200
など間で機能するように.
以下のコードでは、初めて正常に動作します。しかし、2回目はhttpclient.execute
としてこの行に例外をスローしています。
Java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.
ここで何か間違っていることはありますか?-
以下は私のコードです
class Task implements Runnable {
private DefaultHttpClient httpclient = new DefaultHttpClient();
private HttpGet httpGet;
private HttpResponse response;
@Override
public void run() {
try {
httpGet = new HttpGet(
"http://localhost:8080/service/BEService/v1/get/USERID=10000/profile.ACCOUNT.SERVICE
httpGet.getRequestLine();
for (int userId = id; userId < id + noOfTasks; userId++) {
long start = System.nanoTime();
response = httpclient.execute(httpGet);
long end = System.nanoTime() - start;
}
} catch (Exception e) {
LOG.error("Threw a Exception in " + getClass().getSimpleName(), e);
}
}
}
更新コード:-
このようなことをしているなら
class Task implements Runnable {
private DefaultHttpClient httpclient = new DefaultHttpClient();
private HttpGet httpGet;
private HttpResponse response;
@Override
public void run() {
try {
for (int userId = id; userId < id + noOfTasks; userId++) {
httpGet = new HttpGet("http://localhost:8080/service/BEService/v1/get/USERID=10000/profile.ACCOUNT.SERVICE");
httpGet.getRequestLine();
long start = System.nanoTime();
response = httpclient.execute(httpGet);
long end = System.nanoTime() - start;
HttpEntity entity = response.getEntity();
EntityUtils.consume(entity);
}
} catch (Exception e) {
LOG.error("Threw a Exception in " + getClass().getSimpleName(), e);
}
}
}
それでいいですか?
ここで何か間違ったことはありますか?
はい。 ドキュメント に記載されているとおり:
BasicClientConnectionManagerは、一度に1つの接続のみを維持する単純な接続マネージャーです。このクラスはスレッドセーフですが、1つの実行スレッドのみが使用する必要があります。 BasicClientConnectionManagerは、同じルートを持つ後続のリクエストで接続を再利用するよう努力します。ただし、永続的な接続のルートが接続要求のルートと一致しない場合は、既存の接続を閉じて、指定されたルートに対して再度開きます。接続がすでに割り当てられている場合、Java.lang.IllegalStateExceptionがスローされます。
BasicClientConnectionManagerは、デフォルトでHttpClientによって使用されます。
"Multithreaded request execution" を使用して、複数のスレッド間でリクエストを処理できる pooling connection manager を参照してください。
Vanilla DefaultHttpClient
(内部でBasicClientConnectionManager
を使用)を使用していると仮定すると、最初に未解決/最後の応答を消費する必要があります。
EntityUtils.consumeQuietly(httpResponse.getEntity());
それ以外の場合は、DefaultHttpClient
を毎回再割り当てできます。
これは、プール接続マネージャーを使用したRestTemplateの私の構成です。さらに5つの並行スレッドで非常にうまく機能します。
<!-- RestTemplate -->
<beans:bean id="restTemplateYT" class="org.springframework.web.client.RestTemplate">
<beans:constructor-arg ref="httpRequestFactoryYT" />
</beans:bean>
<beans:bean id="httpRequestFactoryYT" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<beans:constructor-arg>
<beans:bean class="org.Apache.http.impl.client.DefaultHttpClient">
<beans:constructor-arg>
<beans:bean class="org.Apache.http.impl.conn.PoolingClientConnectionManager"/>
</beans:constructor-arg>
</beans:bean>
</beans:constructor-arg>
<beans:property name="connectTimeout" value="5000" />
</beans:bean>
Springバージョン:3.1.0