我正在开发一个具有以下特性的客户机和服务器系统:这里的客户机和服务器正在Linux上运行。
有一对冗余服务器主机(用于hw生存能力)。每个主机都有一个固定的IP地址。还有一个浮动IP地址一次被限制在一个主机上。
在过渡期间,备用主机解除浮动IP的绑定,然后新激活的主机绑定到它。绑定是通过ifconfig up/down命令完成的。arping -U用于向交换机告知与地址相关的MAC已更改。
两个服务器主机都连接到同一个交换机。
在此系统中,不使用主机名(fqdn)。
服务器主机正在运行两个java进程和一个erlang进程。
客户端在erlang进程上打开了一个永久侦听套接字,并使用RMI接口和REST接口与Java进程进行通信。泽西诉1.17框架用于REST。所有Java进程都在运行Java1.6。
当客户端使用浮动地址连接到活动服务器时,事情本来很好。有一次,我强迫服务器切换。前一个活动主机解除浮动地址的绑定,而前备用主机绑定到浮动地址。
乐趣从这里开始。根据客户端的运行位置,可以看到三种不同的行为。
B&C是所需的用例。
案件A是最容易解决的。一旦地址没有限制,我就会得到一个套接字异常,我可以对它做出反应,从连接到erlang进程。只需等待一个地址再次被绑定,然后重新连接就可以了。RMI接口是相同的,执行名称查找再次返回指向新活动主机的存根(存根指向固定地址--我可以接受),然后当我发出REST请求时,它们也会被路由到新的活动主机。
案例B提供了一个略有不同的错误,心跳在检测更改中起着作用,但是解决方案是相同的。
令我无法理解的是案例C。在本例中,到erlang进程的连接正正确地从本地主机转移到新的活动主机。RMI名称查找也是在新主机上完成的。
然而,其余的调用是从本地主机(前活动主机)返回数据,而不是从新的活动主机返回数据。这种情况会持续几分钟(通常是3-4分钟),然后事情就会自行解决!我非常努力地努力想办法弄清楚这个,测试,网络挖掘,到目前为止还没有什么好运气。
我认为这种行为可能来自三个方面:
我做了很多假设:
到现在为止,我已经绝望了,准备考虑任何假设;-)
有人能说明在地址移动主机后继续将数据包路由到错误主机的机制吗?
在3到4分钟之后,我们又能说什么呢?这是什么类型的缓存。
谢谢大家的建议。
发布于 2014-03-27 21:35:09
我设法找出了更多的时间来研究这个问题。
我对一些关于HttpUrlConnection实例使用的套接字池的引用进行了更多的搜索。
我发现的一个有趣的链接是:
http://docs.oracle.com/javase/6/docs/technotes/guides/net/http-keepalive.html
它确认默认情况下为HTTP连接保留一个套接字池。底层的套接字保持活动状态。
这意味着当您在每个请求中使用一个新的HttpUrlConnection实例时,您可能会重用已经打开的套接字。这使得客户机更高效,特别是在使用HTTPS的情况下。
在我的示例(用例C)中,Linux提供了一个在两个本地进程之间保持功能的套接字,即使用于打开它的原始IP地址已经消失。
这意味着以前从池打开的套接字现在指向错误的主机。(即本地主机不再与地址相关联,新主机是)。
这就解释了我看到的行为(终于!)。
解决这个问题很容易。
Oracle的文章指出,您可以将系统属性http.keepAlive设置为false (默认为true)。
System.setProperty("http.keepAlive", "false");这使得系统为每个HTTP请求打开一个新的套接字。你失去了效率,但得到了一个客户可以生存的地址移动。这在我的情况下是很关键的(但可能不是一个常见的情况)。
本文还提到了控制池(例如,它的大小)可以做的其他一些事情。
另一种方法可能是在地址交换机上发送一个HTTP头,并将元数据连接设置为关闭。要正确处理这个问题需要更多的技巧,但大多数时候都会保持客户端的有效性。
任何人有更多的见解,请随时提供。
https://stackoverflow.com/questions/22597621
复制相似问题