2012-05-29 8 views
6

Estamos utilizando Apache Camel como motor de orquestación. Por lo general, el siguiente escenario:Apache Camel: por qué la conexión TCP no está cerrada después de recibir 200 OK

cliente envía la solicitud HTTP < -> código de CAMEL < -> servidor externo (s)

La pelota comienza a rodar cuando nuestro cliente envía una solicitud HTTP a nuestro código CAMEL. El código Camel activará servidores externos a través de llamadas HTTP REST. Eventualmente, el código de Camel enviará una respuesta al cliente.

La última acción antes de devolver la respuesta al cliente, el código Camel envía un HTTP GET hacia un servidor externo. Entonces, primero se configura una conexión TCP y luego se envían los datos. Después de un tiempo (esto puede tomar de 5 a 10 segundos), el servidor externo responde con un 200 OK.

Problema: Camel no envía un TCP FIN al servidor externo después de recibir el 200 OK. Como resultado, la conexión TCP permanece abierta ... (el servidor externo luego cierra la conexión TCP después de un tiempo de espera de 200 segundos, pero esto significa que se perdió un recurso TCP durante 200 segundos).

Así, a nivel TCP, es la siguiente:

Camel < ----------> servidor externo

TCP SYN --> 
    <-- TCP SYN,ACK 
    TCP ACK --> 

    HTTP GET --> 
    <-- 200 OK 
    TCP ACK --> 

    <200 seconds later> 
    <-- TCP FIN,ACK 
    TCP ACK --> 

Alguna idea de cómo puedo tener Camel cerrar la Conexión TCP después de haber recibido el 200 OK?

Nota: Intenté agregar el encabezado "Connection: close", pero Camel no agregó el encabezado?! Parecía ignorarlo ...

Este era el código para agregar el encabezado:

exchange.getOut().setHeader("Connection","Close"); 

estoy usando Camel 2.9.1 en un marco de primavera con Eclipse IDE.

+0

¿Qué componente de Camels http usas? –

+0

Hola, estoy usando Camel 2.9.2 (no 2.9.1 como mencioné antes :() y camel-http-2.9.2.jar (y commons-httpclient-3.1.jar). – opstalj

+0

¿Puede reproducir este comportamiento con ¿Algún servidor HTTP? ¿O el servidor del cliente es el único que no cierra la conexión? –

Respuesta

4

Lamentablemente, no vi otra solución que crear una clase HttpHeaderFilterStrategy personalizada que no filtre el encabezado Connection. Luego, antes de enviar mi solicitud al servidor externo, configuro el encabezado "Conexión: cerrar". Tan pronto como se responde a esta solicitud, el código Camel envía un FIN, ACK de TCP para cerrar la conexión TCP.

Más detalles:

1) Crear una clase HttpHeaderFilterStrategy de encargo, por ejemplo: CustomHttpHeaderFilterStrategy

2) adaptar el applicationContext.xml para que apunte a esa clase, por ejemplo:

<bean id="http" class="org.apache.camel.component.http.HttpComponent"> 
    <property name="camelContext" ref="camel"/> 
    <property name="headerFilterStrategy" ref="myHeaderFilterStrategy"/> 
</bean> 

<bean id="myHeaderFilterStrategy" class="com.alu.iptc.com.CustomHttpHeaderFilterStrategy"> 
</bean> 

3) adaptar su código, de modo que se establezca el encabezado Connection: close, p. ej .:

exchange.getOut().setHeader("Connection","close"); 
1

Se debe considerar que las conexiones HTTP1.1 se mantienen activas después del primer mensaje durante un tiempo para permitir que varios archivos se entreguen en una sesión TCP por motivos de rendimiento. Normlly, un servidor http podría cortar las conexiones después de unos segundos para guardar los hilos mientras permite la descarga de múltiples archivos. El componente http Camel probablemente se comportará de la misma manera. http://en.wikipedia.org/wiki/HTTP_persistent_connection

El cliente oficial de HTTP, que Camel se basa en puede ser configurado para usar o no usar conexiones persistentes, pero por defecto es cierto: http://docs.oracle.com/javase/1.5.0/docs/guide/net/http-keepalive.html

Aunque yo no lo he probado, debe ser posible establecer una propiedad del sistema para configurar este

http.keepAlive=<boolean> 

usted debe ser capaz de establecer en el contexto de camello si quieres

<camelContext> 
    <properties> 
     <property key="http.keepAlive" value="false"/> 
    </properties> 
</camelContext> 

Tenga en cuenta que no lo he probado. ¡Si lo haces funcionar, sería bueno escuchar los resultados!

+0

Lástima, lo probé pero no pareció tener ningún efecto ... Debería haber una forma de decirle a la aplicación Camel que toda la información requerida se ha recibido y, por lo tanto, la conexión TCP se puede cerrar, ¿no? – opstalj

+0

intente configurarlo como una propiedad del sistema. El cliente HTTP4 en Java debería recoger esto. –

+0

¿Podría ser esa la diferencia? Estoy usando el plano Componente HTTP y no el HTTP4 ...? – opstalj

Cuestiones relacionadas