2011-12-22 11 views
14

Tengo dos servidores Tomcat que necesitan mantener una conexión constante para reducir el protocolo de enlace SSL. Un servidor (el proxy) se encuentra en una zona desmilitarizada, mientras que el otro está seguro detrás de otro servidor de seguridad. El proxy básicamente solo ejecuta un servlet simple que realiza alguna comprobación de cordura antes de reenviar las solicitudes a la máquina segura. En una solicitud inicial, las máquinas intercambian certificados antes de realizar el trabajo real. Por lo tanto, me gustaría mantener una conexión constante con un tiempo de espera de unos minutos.Tomcat, HTTP Keep-Alive y Java's HttpsUrlConnection

Para hablar con el servidor seguro, el servlet en el proxy usa HttpsUrlConnection. Configuré WireShark y noté que no importa qué valor de keepAliveTimeout establezca para el conector en la máquina segura, la conexión TCP se cierra después de unos 5 o 10 segundos. Este número parece coincidir con lo que he leído es el tiempo de espera predeterminado y cómo maneja Java HTTP Keep-Alive. Este link explica que Java respeta el tiempo de espera Keep-Alive si lo envía el servidor, de lo contrario, utiliza 5 segundos (conexiones directas) o 10 segundos (conexiones proxy) antes de que cierre la conexión.

Lo que estoy tratando de averiguar es cómo puedo obligar a Tomcat a enviar el encabezado Keep-Alive. No, Connection: Keep-Alive, pero Keep-Alive: timeout=x.

Experimenté con el servidor Apache HTTP y la modificación del keepAliveTimeout en httpd.conf hace que el encabezado Keep-Alive cambie su valor de tiempo de espera. Además, Java hace honor a este tiempo de espera.

ACTUALIZACIÓN (23/12/11): Después de ejecutar unas cuantas más experimentos que he intentado batir un poco de código de forma rápida y sucia usando Apache HttpClient (3.1) en lugar de HttpsUrlConnection. Parece que HttpClient, cuando está configurado para usar Keep-Alive, simplemente espera que el servidor cierre la conexión. No sé cuánto tiempo esperará. Estoy disparando para mantener la conexión HTTP activa de 3 a 5 minutos.

+0

"La conexión TCP se cierra después de unos 5 o 10 segundos". ¿Por qué final? El cliente o el servidor? – EJP

+0

Lo cierra el cliente. –

+0

Ya sabe, el escenario que describe; WebServer en las solicitudes de reenvío DMZ a AppServers detrás de un firewall, a menudo se maneja con Apache HTTPD en la DMZ haciendo las cosas https y reenviando las solicitudes a Tomcat AppServers usando conectores AJP (http://tomcat.apache.org/tomcat-4.0). -doc/config/ajp.html). Esta es una forma alternativa de evitar la sobrecarga de SSL. –

Respuesta

6

Pude usar HttpClient 3.1 para mantener abierta la conexión HTTP durante 5 minutos configurando keepAliveTimeout en el conector Tomcat en 300000. Verifiqué utilizando WireShark que el servidor terminará la conexión, mientras que HttpClient simplemente esperará. Las solicitudes posteriores a través de HttpClient reutilizan la conexión TCP existente (evitando cualquier otro apretón de manos SSL). Sin embargo, la clave allí es tener una sola instancia HttpClient (es decir, no crear una instancia cada vez). Esto podría ser obvio para la mayoría, pero no estaba seguro de cuál sería la mecánica API para HTTPClient. En resumen, cree una instancia HttpClient y para cada solicitud (POST, GET, etc.) cree un nuevo PostMethod, GetMethod, etc. Esto causará que la conexión TCP sea reutilizada.

1

Java API Http(s)UrlConnection cumple perfectamente con la información Keep-Alive y gestiona un conjunto de conexiones por servidor host de acuerdo con following detailed explanation (léalo detenidamente, cada detalle es importante).

En ese caso, su código tiene que leer completamente los búferes, cerrar las secuencias y leer el error en el caso de IOException.

Por supuesto HttpClient tiene menos restricciones, pero la mejor manera de manejar su situación es usar su MultiThreadedHttpConnectionManager gracias al following guidelines.

4

En Tomcat que lograron establecer las cabeceras en mi HttpServelet usando HttpServletResponse.addHeader() así:

response.addHeader("Connection", "Keep-Alive"); 
    response.addHeader("Keep-Alive", "timeout=60000"); 

confirmé con Wireshark que esto funciona con HttpURLConnection en el lado del cliente. No funciona si no configura el encabezado "Conexión", por lo que debe establecer ambos.

+0

El encabezado de conexión debe ser establecido automáticamente por tomcat si se agrega la configuración Keep-Alive. Está duplicando Keep-Alive desde server.xml de tomcat y también su código que devuelve un encabezado Keep-Alive personalizado. Existe una gran posibilidad de que ambos se desincronicen y, en el peor de los casos, si el tiempo de espera de la aplicación fue de alguna manera más largo que el de Tomcat o el tomcat decide cerrar, el cliente fallará. – kisna

Cuestiones relacionadas