您的位置:首页 > 理论基础 > 计算机网络

由于使用 xfire/HttpMethod 造成Socket连接池满的问题及解决办法

2012-05-18 11:21 375 查看
由于使用 xfire/HttpMethod 造成Socket连接池满的问题及解决办法

I/O exception (java.net.BindException) caught when processing request: Address already in use: connect (平台报出异常,传说该错误又socket连接满引起,故为上标题)

使用 XFire 访问webService, 运行一段时间后, 使用netstat -ano命令,发现服务器上有大量的CLOSE_WAIT连接,导致之后的WebService服务访问经常失败。

原因如下:

CLOSE_WAIT是Tcp状态迁移中的一个

当服务端主动关闭而客户端没来及响应进入的一个的状态,此状态TCP层默认时间大概为2小时左右

故导致了达到最大连接数出现了假死

解决办法:

对于使用httpclient的程序

只需要在HttpMethod method = new GetMethod("url");加上一行HTTP头的设置即可

method.setRequestHeader("Connection", "close");

对于使用xFire的程序

xFire是基于PostMethod实现的,CommonsHttpMessageSender类中会读取DISABLE_KEEP_ALIVE属性如果值为true的话,那么就会将PostMethod加入 Connection close的属性

在实例化httpClient对象后,添加下面一行代码即可

client.setProperty(CommonsHttpMessageSender.DISABLE_KEEP_ALIVE, "true")

=====================================================================================================

XFire平台下的连接超时设置

100 (continue) read timeout. Resume sending the request

public Client loadClient() throws MalformedURLException, Exception{

Client client = new Client(new URL(url));

client.setTimeout(20000);

HttpClientParams params = new HttpClientParams();

// 避免'Expect: 100-continue' handshake

params.setParameter(HttpClientParams.USE_EXPECT_CONTINUE,Boolean.FALSE);

//设置ws连接超时时间

params.setParameter(HttpClientParams.CONNECTION_MANAGER_TIMEOUT, 20000l);

client.setProperty(CommonsHttpMessageSender.HTTP_CLIENT_PARAMS,params);

return client;

}

以上的做法在实际项目中发现行不通,现修改为:

URL _url = new URL(url);

HttpURLConnection httpConnection = (HttpURLConnection)_url.openConnection();

httpConnection.setReadTimeout(20000);//设置http连接的读超时,单位是毫秒

httpConnection.connect();

Client _client = new Client(httpConnection.getInputStream(), null);

_client.setProperty(CommonsHttpMessageSender.HTTP_TIMEOUT, String.valueOf( 20000 ));//设置发送的超时限制,单位是毫秒;

_client.setProperty(CommonsHttpMessageSender.DISABLE_KEEP_ALIVE, "true");

_client.setProperty(CommonsHttpMessageSender.DISABLE_EXPECT_CONTINUE, "true");

实践检验,可行!

======================================================================================================

以上从网上搜到两种解决办法,首先觉的最终原因是因为使用 xfire/HttpMethod 造成Socket连接池满,所以标题使用此标题。

第一种方法和第二种方法解决理论一致,出发点也一致,只不过设置的参数不一致。

其他,,,是否能解决正在论证中。。。

另外还有中办法,网上说这种办法的人很多,不过我觉得是治标不治本

短时间内new socket操作过多

而socket.close()操作并不能立即释放绑定的端口

而是把端口设置为TIME_WAIT状态

过段时间(默认240s)才释放(用netstat -na可以看到)

最后系统资源耗尽

(windows上是耗尽了pool of ephemeral ports 这段区间在1024-5000之间)

可以考虑增加端口数量来解决,不过你为何不考虑用Socket池呢?让一个Socket重复利用呢?

以下是修改方法

默认最大数量的短暂 TCP 端口为 5000 ' 适用于 ' 部分中包含产品中。 这些产品中已添加新参数。 要增加最大值是短暂端口, 请按照下列步骤操作:

1.

启动注册表编辑器。

2.

注册表, 中找到以下子项, 然后单击 参数 :

HKEY _ LOCAL _ MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

3.

在 编辑 菜单, 单击 新建 , 然后添加以下注册表项:

MaxUserPort 值名称:

值类型: DWORD

值数据: 65534

有效范围: 5000 - 65534 (十进制)

默认: 0x1388 5000 (十进制)

说明: 此参数控制程序从系统请求任何可用用户端口时所用最大端口数。 通常, 1024 的值和含 5000 之间分配临时 (短期) 端口。

4.

退出注册表编辑器, 并重新启动计算机。

注意 一个附加 TCPTimedWaitDelay 注册表参数决定多久关闭端口等待可以重用关闭端口。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐