2011-11-20 16 views
6

probé el siguiente ejemplo de Apache cliente http:HTTPClient conexión 4.x reutilización no suceda

http://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientMultiThreadedExecution.java

que ajustar el tamaño de la piscina como máximo 5 y correr diez hilos. Después de ejecutar este código, cuando verifico netstat, veo 10 conexiones TCP abiertas. Esperaba que las conexiones fueran reutilizadas. Por qué es esto ? Me estoy perdiendo de algo ?

Código fragmento es de la siguiente manera:

public class ClientMultiThreadedExecution { 
public static void main(String[] args) throws Exception { 

    SchemeRegistry schemeRegistry = new SchemeRegistry(); 
    schemeRegistry.register(
    new Scheme("http", 18080, PlainSocketFactory.getSocketFactory())); 

    ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(schemeRegistry); 
    cm.setDefaultMaxPerRoute(5); 
    cm.setMaxTotal(5); 


    HttpClient httpclient = new DefaultHttpClient(cm); 
    try { 
     // create an array of URIs to perform GETs on 
     String uri = "http://test.webservice.com:18080/TestServlet"; 
     String data = "This is a test message"; 

     System.out.println("Started at: " + new Date()); 
     // creating 10 threads 
     PostThread[] threads = new PostThread[10]; 

     for (int i = 0; i < threads.length; i++) { 
     HttpPost httpPost = new HttpPost(uri); 
     threads[i] = new PostThread(httpclient, httpPost, data, i + 1); 
      threads[i].start(); 
      //Thread.sleep(1000); 
     } 

     // join the threads 
     for (int j = 0; j < threads.length; j++) { 
      threads[j].join(); 
     } 

    } finally { 
     // When HttpClient instance is no longer needed, 
     // shut down the connection manager to ensure 
     // immediate deallocation of all system resources 
     System.out.println("Ended at: " + new Date()); 
     httpclient.getConnectionManager().shutdown(); 
    } 
} 

/** 
* A thread that performs a POST. 
*/ 
static class PostThread extends Thread { 

    private final HttpClient httpClient; 
    private final HttpContext context; 
    private final HttpPost httpPost; 
    private final int id; 
    private final String data; 

    public PostThread(HttpClient httpClient, HttpPost httpPost, String data, int id) { 
     this.httpClient = httpClient; 
     this.context = new BasicHttpContext(); 
     this.httpPost = httpPost; 
     this.id = id; 
     this.data = data; 
    } 

    /** 
    * Executes the PostMethod and prints some status information. 
    */ 
    @Override 
    public void run() { 

     //System.out.println(id + " - about to get something from " + httpPost.getURI()); 

     try { 

      List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1); 
      nameValuePairs.add(new BasicNameValuePair("XML",data)); 
      httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs,"UTF-8")); 

      // execute the method 
      HttpResponse response = httpClient.execute(httpPost, context); 

      //System.out.println(id + " - get executed"); 
      // get the response body as an array of bytes 
      if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) 
       System.out.println("Success"); 

      //Is this step necessary ?? Need to check as only status code is required 
      //httpPost.abort(); 
      //HttpEntity entity = response.getEntity(); 

      //And this ? 
      //EntityUtils.consume(entity); 

     } catch (Exception e) { 
      httpPost.abort(); 
      System.out.println(id + " - error: " + e); 
     } 
    } 

}} 
+1

La solución fue mencionar específicamente la versión del protocolo como HTTP_1_1: 'HttpProtocolParams.setVersion (params, HttpVersion.HTTP_1_1);'. La puesta en común luego funcionó. – Dunxton

+0

¿Qué necesitamos para mantener en lugar de params? ¿Qué valor y dónde tenemos que colocar esta declaración en el código – Labeo

Respuesta

11

 //Is this step necessary ?? Need to check as only status code is required 
     //httpPost.abort(); 
     //HttpEntity entity = response.getEntity(); 

     //And this ? 
     //EntityUtils.consume(entity); 

adivina qué? Es.

Uno DEBE garantizar que el contenido de respuesta se consuma para que la conexión subyacente se devuelva al administrador de conexión. La invocación de EntityUtils#consume o httpUriRequest#abort activa la liberación de la conexión a la agrupación. La diferencia es que el primero intenta mantener viva la conexión mientras que el segundo no.

+0

¿Qué hay de este bloque de código? 'catch (Excepción e) { httpPost.abort(); System.out.println (id + "- error:" + e); } 'Siempre que se produce una excepción, se llama a httpPost.abort(). Sin embargo, lo que observo es que la misma conexión abortada todavía se está distribuyendo a otros hilos y todos ellos se salieron con el mensaje 'java.io.IOException: Request already aborted'. Por qué pasó esto ? – Dunxton

+2

@Dunxton Las conexiones abortadas se descartan y expulsan de la agrupación de inmediato. Está intentando reutilizar una solicitud abortada. No hagas eso. Los objetos de solicitud son baratos. – oleg

Cuestiones relacionadas