Подтвердить что ты не робот

Недопустимое использование BasicClientConnManager: соединение все еще выделено

Я звоню на URL REST и пытаюсь измерить, сколько времени он принимает, чтобы получить ответ.

Я использую DefaultHttpClient для этого, чтобы получить ответ от REST URL.

В моей нижеперечисленной программе каждый поток будет работать в определенном диапазоне. Как и каждый поток будет работать между 1 - 100, а второй поток будет работать между 101 - 200 и т.д.

SO в моем нижнем коде, он работает нормально. Но во второй раз он второй раз исключает эту строку 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);
        }
    }
}

тогда это нормально или нет?

4b9b3361

Ответ 1

Есть ли что-то неправильное, что я здесь делаю?

Да. Как указано в документах:

BasicClientConnectionManager - это простой диспетчер соединений, который поддерживает только одно соединение за раз. Хотя этот класс поточно-безопасный, он должен использоваться только одним исполнительным потоком. BasicClientConnectionManager будет пытаться повторно использовать соединение для последующих запросов с тем же маршрутом. Это будет, однако, закрыть существующее соединение и повторно открыть его для данного маршрут, если маршрут постоянного соединения не соответствует запроса соединения. Если соединение уже было выделено, затем вызывается java.lang.IllegalStateException.

BasicClientConnectionManager используется по умолчанию для HttpClient.

См. "Выполнение многопоточного запроса" о том, как использовать диспетчер подключений , который может обрабатывать запросы через несколько потоков.

Ответ 2

Предполагая, что вы используете vanilla DefaultHttpClient (который использует BasicClientConnectionManager внутренне), вам сначала нужно использовать выдающийся/последний ответ.

EntityUtils.consumeQuietly(httpResponse.getEntity());

В противном случае вы можете перераспределять DefaultHttpClient каждый раз.

Источник: Обходной путь для не выключения DefaultHttpClient() каждый раз после использования

Ответ 3

Это моя конфигурация для 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