如何确保我的HttpClient 4.1不会泄漏套接字? [英] How can I ensure that my HttpClient 4.1 does not leak sockets?
问题描述
我的服务器使用来自内部Web服务的数据来构建其响应,基于每个请求。我正在使用Apache HttpClient 4.1来发出请求。每个初始请求将导致对Web服务的大约30个请求。其中,4 - 8最终将插入CLOSE_WAIT中的套接字,而这些套接字永远不会被释放。最终这些卡住的套接字超过了我的ulimit,我的进程耗尽了文件描述符。
My server uses data from an internal web service to construct its response, on a per request basis. I'm using Apache HttpClient 4.1 to make the requests. Each initial request will result in about 30 requests to the web service. Of these, 4 - 8 will end up with sockets stuck in CLOSE_WAIT, which never get released. Eventually these stuck sockets exceed my ulimit and my process runs out of file descriptors.
我不想只提高我的ulimit(1024),因为那只会掩盖问题。
I don't want to just raise my ulimit (1024), because that will just mask the problem.
我转移到HttpClient的原因是java.net.HttpUrlConnection的行为方式相同。
The reason I've moved to HttpClient is that java.net.HttpUrlConnection was behaving the same way.
我已经尝试了每个请求移动到SingleClientConnManager,并在其上调用client.getConnectionManager()。shutdown(),但套接字仍然卡住了。
I have tried moving to a SingleClientConnManager per request, and calling client.getConnectionManager().shutdown() on it, but sockets still end up stuck.
我是否应该尝试解决这个问题,以便在没有运行请求时最终得到0个开放套接字,或者我应该专注于请求持久性和池化?
Should I be trying to solve this so that I end up with 0 open sockets while there are no running requests, or should I be concentrating on request persistence and pooling?
For清晰度我包括一些可能相关的细节:
For clarity I'm including some details which may be relevant:
操作系统:Ubuntu 10.10
OS: Ubuntu 10.10
JRE:1.6。 0_22
JRE: 1.6.0_22
语言:Scala 2.8
Language: Scala 2.8
示例代码:
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()
测试:netstat -a | grep {myInternalWebServiceName} | grep CLOSE_WAIT
Test: netstat -a | grep {myInternalWebServiceName} | grep CLOSE_WAIT
(列出我的进程处于CLOSE_WAIT状态的套接字)
(Lists sockets for my process that are in CLOSE_WAIT state)
发表评论讨论:
此代码现在演示了正确的用法。
This code now demonstrates correct usage.
推荐答案
需要亲...主动从连接池中驱逐过期/空闲连接,因为阻塞I / O模型连接无法对I / O事件做出反应,除非正在读取/写入它们。有关详细信息,请参阅
One needs to pro-actively evict expired / idle connections from the connection pool, as in the blocking I/O model connections cannot react to I/O events unless they are being read from / written to. For details see
http://hc.apache.org/httpcomponents-client-dev/tutorial/html/connmgmt.html#d4e631
这篇关于如何确保我的HttpClient 4.1不会泄漏套接字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!