Il mio server utilizza i dati da un servizio Web interno per costruire la risposta, in base alle richieste. Sto usando Apache HttpClient 4.1 per fare le richieste. Ogni richiesta iniziale comporterà circa 30 richieste al servizio web. Di questi, 4 - 8 finiranno con socket bloccati in CLOSE_WAIT, che non verranno mai rilasciati. Alla fine questi socket bloccati superano il mio limite e il mio processo si esaurisce nei descrittori di file.Come posso assicurarmi che il mio HttpClient 4.1 non abbia perdite di prese?
Non voglio solo aumentare il mio ulimit (1024), perché questo si limita a mascherare il problema.
Il motivo per cui mi sono spostato su HttpClient è che java.net.HttpUrlConnection si comportava allo stesso modo.
Ho provato a passare a un SingleClientConnManager per richiesta ea chiamare client.getConnectionManager(). Shutdown() su di esso, ma i socket rimangono bloccati.
Dovrei provare a risolvere questo in modo che finisca con 0 socket aperti mentre non ci sono richieste in esecuzione, o dovrei concentrarmi sulla persistenza delle richieste e sul pool?
Per chiarezza sto compresi alcuni dettagli che possono essere rilevanti:
OS: Ubuntu 10.10
JRE: 1.6.0_22
Lingua: Scala 2.8
codicecampione:
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()
Test: netstat -a | grep {myInternalWebServiceName} | grep CLOSE_WAIT
(Liste prese per il mio processo che si trovano in stato CLOSE_WAIT)
Invia un commento discussione:
Questo codice ora dimostra un uso corretto.
Grazie per la risposta, sono d'accordo che la documentazione suggerisce che dovrebbe essere una misura efficace. Il numero di socket orfani in CLOSE_WAIT cresce ancora in modo affidabile con il depuratore off-thread implementato, quindi non è stato efficace. Ho aggiunto alcuni dettagli di implementazione alla mia domanda. –
I ritroso. Non mi ero reso conto che nell'effettivo codice dell'applicazione stavo facendo richieste di immagini supplementari per eseguire la logica di business. Stavano ancora usando i metodi WS.url prima dell'introduzione di HttpClient e stavano lasciando i socket alle spalle. –
Collegamento interrotto. (Si prega di includere titoli e descrizioni con collegamenti.) Forse questa è la stessa informazione? http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html – danorton