2011-11-20 13 views
6

ho provato il seguente esempio di Apache client http:HTTPClient 4.x connessione non riutilizzare accadendo

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

ho impostato la dimensione massima del pool di 5 ed eseguire dieci thread. Dopo aver eseguito questo codice, quando controllo netstat, vedo 10 connessioni TCP aperte. Mi aspettavo che le connessioni fossero riutilizzate. Perchè è questo ? Mi sto perdendo qualcosa ?

snippet di codice viene, come di seguito:

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 soluzione era quella di parlare specificamente la versione del protocollo come HTTP_1_1: 'HttpProtocolParams.setVersion (params, HttpVersion.HTTP_1_1);'. La riunione poi ha funzionato. – Dunxton

+0

Cosa dobbiamo mantenere al posto di params indica quale valore e dove dobbiamo inserire questa affermazione nel codice – Labeo

risposta

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

indovinate cosa? È.

Uno DEVE assicurarsi che il contenuto della risposta venga consumato in modo che la connessione sottostante venga restituita alla gestione connessione. Il richiamo di EntityUtils#consume o httpUriRequest#abort attiva il rilascio della connessione al pool. La differenza è che il primo tenta di mantenere in vita la connessione mentre il secondo no.

+0

Che ne dici di questo blocco di codice? 'catch (Exception e) { httpPost.abort(); System.out.println (id + "- errore:" + e); } Ogni volta che si verifica un'eccezione, viene chiamato httpPost.abort(). Tuttavia, quello che osservo è che, la stessa connessione interrotta viene ancora distribuita ad altri thread e tutti vengono eliminati con il messaggio 'java.io.IOException: Request already aborted'. Perché succede? – Dunxton

+2

@Dunxton Le connessioni interrotte vengono scartate e sfrattate immediatamente dalla piscina. Stai tentando di riutilizzare una richiesta interrotta. Non farlo. Gli oggetti di richiesta sono economici. – oleg

Problemi correlati