web-dev-qa-db-fra.com

Utilisation non valide de BasicClientConnManager: connexion toujours allouée

J'appelle à REST URL et j'essaie de mesurer le temps qu'il faut pour récupérer la réponse.

J'utilise DefaultHttpClient pour cela pour obtenir la réponse de REST URL.

Dans mon programme ci-dessous, chaque thread travaillera sur une plage particulière. Comme chaque thread fonctionnera entre 1 - 100 et le deuxième thread fonctionneront entre 101 - 200 etc.

SO dans mon code ci-dessous, pour la première fois cela fonctionne bien. Mais pour la deuxième fois, il lève une exception sur cette ligne httpclient.execute pour la deuxième fois

Java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.

Y a-t-il quelque chose que je fais de mal ici? -

Ci-dessous est mon code-

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);
        }
    }
}

Code mis à jour: -

Si je le fais quelque chose comme ça-

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);
        }
    }
}

alors c'est bien ou pas?

40
AKIWEB

Y a-t-il quelque chose que je fais de mal ici?

Oui. Comme indiqué dans les documents :

BasicClientConnectionManager est un gestionnaire de connexions simple qui ne gère qu'une seule connexion à la fois. Même si cette classe est thread-safe, elle ne doit être utilisée que par un thread d'exécution. BasicClientConnectionManager fera un effort pour réutiliser la connexion pour les requêtes suivantes avec le même itinéraire. Il fermera cependant la connexion existante et la rouvrira pour l'itinéraire donné, si l'itinéraire de la connexion persistante ne correspond pas à celui de la demande de connexion. Si la connexion a déjà été allouée, Java.lang.IllegalStateException est levée.

BasicClientConnectionManager est utilisé par HttpClient par défaut.

Voir "Exécution de requêtes multithread" sur la façon d'utiliser un gestionnaire de connexions de pool qui peut gérer les requêtes sur plusieurs threads.

44
Ryan Stewart

En supposant que vous utilisez Vanilla DefaultHttpClient (qui utilise BasicClientConnectionManager en interne), vous devez d'abord consommer la réponse en attente/dernière.

EntityUtils.consumeQuietly(httpResponse.getEntity());

Sinon, vous pouvez réaffecter DefaultHttpClient à chaque fois.

Source: solution de contournement pour ne pas arrêter DefaultHttpClient () à chaque fois après utilisation

40
kevinarpe

Ceci est ma configuration pour RestTemplate en utilisant le gestionnaire de connexions de pool. Cela fonctionne très bien dans 5 autres threads simultanés.

<!-- 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>

Version printemps: 3.1.0

1
Jerry Chen