2009-12-10 6 views
7

Estamos utilizando HTTPClient para implementar una API REST.¿Por qué es más eficiente en cuanto a la memoria leer la entrada como secuencia vs. cadena?

que estamos leyendo la respuesta del servidor usando:

method = new PostMethod(url); 
HttpClient client = new HttpClient(); 
int statusCode = client.executeMethod(method); 
String responseBody = method.getResponseBodyAsString(); 

Cuando hacemos esto obtenemos la siguiente advertencia:

Dec 9, 2009 7:41:11 PM org.apache.commons.httpclient.HttpMethodBase getResponseBody 
WARNING: Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended. 

El docs van a decir:

HttpClient es capaz de transmitir de manera eficiente solicitud/respuesta del cuerpo. Las entidades grandes pueden enviarse o recibirse sin estar almacenadas en la memoria. Esto es especialmente crítico si se pueden ejecutar métodos HTTP al mismo tiempo. Si bien existen métodos de conveniencia para tratar con entidades tales como cadenas o matrices de bytes , se desaconseja su uso. A menos que se utilicen con cuidado, pueden fácilmente llevar a condiciones de falta de memoria, ya que implican el almacenamiento en búfer de la entidad completa en la memoria.

Así que mi pregunta es, si necesita la respuesta completa como String (es decir, para almacenar en un DB, o analizar usando DOM), ¿por qué es más eficiente utilizar una transmisión?

Respuesta

13

Es más eficaz utilizar una corriente en lugar de obtener toda la entidad como String ya que este último significa que

  1. todo el contenido de la respuesta deben leerse antes de que puedan ser devueltos a su código y
  2. no se puede devolver el control a su código hasta que el servidor haya enviado toda la respuesta.

Si procesó la respuesta como una secuencia, entonces lo que realmente está haciendo es procesarla N bytes a la vez. Esto significa que puede comenzar a procesar el primer segmento de respuesta mientras el servidor remoto sigue enviando el siguiente segmento de datos. Por lo tanto, esto tiene más sentido como un método de acceso si su caso de uso le permite procesar los datos tal como se reciben.

Sin embargo, si necesita toda la respuesta como una Cadena por cualquier razón, entonces todas las eficiencias del método de transmisión no tienen ninguna relación con usted, porque incluso si lee la respuesta en piezas, aún necesita esperar la respuesta completa, y que todo esté contenido en una sola cadena, antes de poder procesarla.

La eficiencia del uso de una transmisión solo está disponible para usted si tiene un caso de uso donde puede comenzar a procesar la respuesta antes de tener todo el cuerpo de respuesta.

4

Todo el proceso no es más eficiente con la memoria. Si lee de un flujo y lo pone en una cadena, solo está separando el proceso en dos partes para que la clase HttpClient no lo note.

Si realmente necesita toda la cadena, puede ignorar la advertencia. Depende de usted asegurarse de que no utilice demasiada memoria por solicitud, de modo que el servidor no pueda ser derribado fácilmente por un ataque DoS.

1

su pregunta confunde el punto.

si necesita absolutamente toda la respuesta como una cadena a continuación, hacer eso,

pero si se puede en absoluto salirse con la suya, utilice corrientes.

cuando carga toda la respuesta en una cadena, todo el cuerpo de respuesta está presente en la memoria al mismo tiempo.

utilizando transmisiones, solo una pequeña parte de la respuesta se mantiene en la memoria a la vez.

la documentación dice que, especialmente con múltiples solicitudes grandes a la vez, cargar todo el cuerpo de la solicitud en una cadena requerirá mucha memoria.

0

Si está analizando un org.w3c.Document (o mejor aún, un org.jdom.Document), es realmente fácil utilizar directamente la transmisión. Ejemplo:

org.apache.http.HttpResponse hr = httpClient.execute(httpRequest); 
org.apache.http.HttpEntity he = hr.getEntity(); 
org.jdom.input.SAXBuilder builder = new SAXBuilder(); 
org.jdom.Document document = builder.build(he.getContent()); 
Cuestiones relacionadas