2012-05-13 8 views
14

Estoy ejecutando pruebas de carga para mi aplicación. Tengo dos servidores: uno con mi aplicación y un servidor ficticio que es responsable de obtener respuestas.obtener NoHttpResponseException para la prueba de carga

En mi servidor ficticio Tengo el siguiente código JSP:

<%@ page import="java.util.Random" %> 
<%@ page language="java" %> 
<%@ page session="false" %> 
<% 
    String retVal = "some json string"; 
    Thread.sleep(50); 
%> 

estoy ejecutando la aplicación con tomcat7. Mi grupo de conexión server.xml (en ambos servidores) se parece a:

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="1500" minSpareThreads="1000" prestartminSpareThreads="true" /> 
<Connector port="9031" protocol="HTTP/1.1" 
      connectionTimeout="20000" 
      maxConnections="4000" 
      executor="tomcatThreadPool" 
      redirectPort="8443" /> 

El código java estoy corriendo de los servidores es:

HttpPost post = new HttpPost(bidderUrl); 
post.setHeader("Content-Type", "application/json");  
// I'm using http client with ThreadSafeClientConnManager 
// total conn = 500, max conn per route = 100, timeout=500millis 
HttpClient httpClient = httpClientFactory.getHttpClient(); 
    try { 
     post.setEntity(new StringEntity(jsobBidRequest)); 
     HttpResponse response = httpClient.execute(post); 
     ... 
    catch (NoHttpResponseException e){ 
     log.error(e); 
    } 

estoy corriendo Jmetter con 50 hilos concurrentes (sin un bucle) y obtener una gran cantidad de excepciones como esto:

org.apache.http.NoHttpResponseException The target server failed to respond 

Mientras estoy corriendo solo 5 o 10 hilos concurrentes todo funciona bien.

¿Podría por favor avisarme qué podría estar mal en mi configuración? Para mi comprensión, no veo ningún error para las 50 solicitudes de subprocesos concurrentes.

Respuesta

30

He encontrado la causa del problema.

Por algún motivo, la conexión se vuelve inválida y el grupo no la conoce.

En este caso, se lanza el NoHttpResponseException y la solicitud simplemente falla. Pensé que tales problemas deberían resolverse en la capa del grupo de clientes HTTP y ser transparentes para mi código, pero esto no es lo que hace.

Para resolver este problema, el cliente HTTP en HttpRequestRetryHandler debe ser anulado:

ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(schemeRegistry); 
... 
DefaultHttpClient httpClient = new DefaultHttpClient(cm, params); 
httpClient.setHttpRequestRetryHandler(new HttpRequestRetryHandler() { 
    @Override 
    public boolean retryRequest(IOException exception, int executionCount, 
           HttpContext context) { 
     if (executionCount > 3) { 
      LOGGER.warn("Maximum tries reached for client http pool "); 
       return false; 
     } 
     if (exception instanceof org.apache.http.NoHttpResponseException) { 
      LOGGER.warn("No response from server on " + executionCount + " call"); 
      return true; 
     } 
     return false; 
     } 
    }); 
+1

¡Julias, esto es muy útil! Muchas gracias por publicar su solución. Es exactamente lo que estoy buscando. – trillions

+0

Su solución también me ayudó. En mi caso, la excepción NoHttpResponseException solo ocurría ocasionalmente cuando tenía el antivirus activado. El antivirus siempre ejecuta un escaneo cuando se envía una solicitud http, y en ocasiones demora un poco más, lo que hace que la solicitud falle. – Seigo

+0

@Seigo - Entiendo que este es un hilo viejo, pero ¿tenía un executionTimeout debido al cual las solicitudes estaban fallando? ¿Qué configuración hizo que las solicitudes fallaran? –

1

me publicó un comentario en el defecto registrado por lo https://issues.apache.org/jira/browse/HTTPCLIENT-1610. Como puede ver, una vez que reduzco el tiempo de validación previa a la reutilización de conexión http inactivo de los 2000 ms predeterminados a algo así como 100 ms, ya no veo ninguna excepción NoHttpResponseException. No he probado para averiguar cuál es el valor umbral en mi entorno para anular el uso de conexión fija, pero 100 ms definitivamente es lo suficientemente corto en mi entorno.

4

Esta solución es para la versión HttpClient 4.5 y posterior. DefaultHttpClient está en desuso.

HttpClientBuilder clientBuilder = HttpClients.custom(); 
clientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, false)); 
Cuestiones relacionadas