Mi servidor utiliza datos de un servicio web interno para construir su respuesta, por solicitud. Estoy usando Apache HttpClient 4.1 para hacer las solicitudes. Cada solicitud inicial dará como resultado aproximadamente 30 solicitudes al servicio web. De estos, 4 - 8 terminarán con enchufes bloqueados en CLOSE_WAIT, que nunca se liberarán. Finalmente, estos sockets atascados exceden mi ulimit y mi proceso se queda sin descriptores de archivo.¿Cómo puedo asegurarme de que mi HttpClient 4.1 no gotea enchufes?
No quiero solo levantar mi ulimit (1024), porque eso enmascara el problema.
La razón por la que me he mudado a HttpClient es que java.net.HttpUrlConnection se comportaba de la misma manera.
He intentado moverme a un SingleClientConnManager por solicitud, y llamar a client.getConnectionManager(). Shutdown() sobre él, pero los sockets todavía terminan bloqueados.
¿Debería tratar de resolver esto para que termine con 0 sockets abiertos mientras no hay solicitudes en ejecución, o debería concentrarme en la persistencia de las solicitudes y la puesta en común?
Para mayor claridad que estoy incluyendo algunos detalles que pueden ser relevantes:
OS: Ubuntu 10.10
JRE: 1.6.0_22
Idioma: Scala 2,8
códigomuestra:
val cleaner = Executors.newScheduledThreadPool(1)
private val client = {
val ssl_ctx = SSLContext.getInstance("TLS")
val managers = Array[TrustManager](TrustingTrustManager)
ssl_ctx.init(null, managers, new java.security.SecureRandom())
val sslSf = new org.apache.http.conn.ssl.SSLSocketFactory(ssl_ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
val schemeRegistry = new SchemeRegistry()
schemeRegistry.register(new Scheme("https", 443, sslSf))
val connection = new ThreadSafeClientConnManager(schemeRegistry)
object clean extends Runnable{
override def run = {
connection.closeExpiredConnections
connection.closeIdleConnections(30, SECONDS)
}
}
cleaner.scheduleAtFixedRate(clean,10,10,SECONDS)
val httpClient = new DefaultHttpClient(connection)
httpClient.getCredentialsProvider().setCredentials(new AuthScope(AuthScope.ANY), new UsernamePasswordCredentials(username,password))
httpClient
}
val get = new HttpGet(uri)
val entity = client.execute(get).getEntity
val stream = entity.getContent
val justForTheExample = IOUtils.toString(stream)
stream.close()
Prueba: netstat -a | grep {myInternalWebServiceName} | grep CLOSE_WAIT
(Listas de tomas de corriente para mi proceso que se encuentran en estado CLOSE_WAIT)
Enviar un comentario de discusión:
Este código ahora demuestra el uso correcto.
Gracias por su respuesta, estoy de acuerdo en que la documentación sugiere que debe ser una medida eficaz. Sin embargo, el número de sockets huérfanos en CLOSE_WAIT sigue creciendo de manera confiable con ese limpiador sin hilos implementado, por lo que no ha sido efectivo. He agregado algunos detalles de implementación a mi pregunta. –
Me retracto. No me había dado cuenta de que en el código de la aplicación real estaba haciendo solicitudes de imágenes suplementarias para realizar la lógica comercial. Seguían usando los métodos WS.url anteriores a la introducción de HttpClient, y dejaban los sockets atrás. –
Enlace roto. (Por favor incluya títulos y descripciones con enlaces.) ¿Tal vez esta es la misma información? http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html – danorton