首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在将主机的动态地址移动到另一个主机后,Java客户端仍然连接到旧主机。

在将主机的动态地址移动到另一个主机后,Java客户端仍然连接到旧主机。
EN

Stack Overflow用户
提问于 2014-03-23 21:54:10
回答 1查看 340关注 0票数 0

我正在开发一个具有以下特性的客户机和服务器系统:这里的客户机和服务器正在Linux上运行。

有一对冗余服务器主机(用于hw生存能力)。每个主机都有一个固定的IP地址。还有一个浮动IP地址一次被限制在一个主机上。

在过渡期间,备用主机解除浮动IP的绑定,然后新激活的主机绑定到它。绑定是通过ifconfig up/down命令完成的。arping -U用于向交换机告知与地址相关的MAC已更改。

两个服务器主机都连接到同一个交换机。

在此系统中,不使用主机名(fqdn)。

服务器主机正在运行两个java进程和一个erlang进程。

客户端在erlang进程上打开了一个永久侦听套接字,并使用RMI接口和REST接口与Java进程进行通信。泽西诉1.17框架用于REST。所有Java进程都在运行Java1.6。

当客户端使用浮动地址连接到活动服务器时,事情本来很好。有一次,我强迫服务器切换。前一个活动主机解除浮动地址的绑定,而前备用主机绑定到浮动地址。

乐趣从这里开始。根据客户端的运行位置,可以看到三种不同的行为。

  • ( A)客户端在与主机不同的网络上运行(到达服务器需要路由)。
  • ( B)客户端运行在原来的备用主机上(请记住,这两个服务器主机都在)同一个网络/交换机。
  • 客户端正在最初活动的主机上运行。

B&C是所需的用例。

案件A是最容易解决的。一旦地址没有限制,我就会得到一个套接字异常,我可以对它做出反应,从连接到erlang进程。只需等待一个地址再次被绑定,然后重新连接就可以了。RMI接口是相同的,执行名称查找再次返回指向新活动主机的存根(存根指向固定地址--我可以接受),然后当我发出REST请求时,它们也会被路由到新的活动主机。

案例B提供了一个略有不同的错误,心跳在检测更改中起着作用,但是解决方案是相同的。

令我无法理解的是案例C。在本例中,到erlang进程的连接正正确地从本地主机转移到新的活动主机。RMI名称查找也是在新主机上完成的。

然而,其余的调用是从本地主机(前活动主机)返回数据,而不是从新的活动主机返回数据。这种情况会持续几分钟(通常是3-4分钟),然后事情就会自行解决!我非常努力地努力想办法弄清楚这个,测试,网络挖掘,到目前为止还没有什么好运气。

我认为这种行为可能来自三个方面:

  • 操作系统(即内核tcp/ip处理)
  • Java或其标准库
  • 泽西图书馆

我做了很多假设:

  • Linux内核-IP堆栈正在缓存连接,并且直到缓存超时时才意识到地址已经移动。我试着用各种命令冲洗它,不去。与erlang的连接和名称查找工作的事实使我倾向于相信内核不会在这里造成问题。
  • 我认为java或VM的内部可能会有一些特权的java来进行Java操作。事实上,名称查找工作,可能也使这一点无效。
  • 我的最后一个假设是,泽西岛正在进行某种缓存。 网络正在谈论Http连接池。实际上,这可能是由Java完成的HttpUrlConnection池。我试图了解更多关于这一点,但只找到模糊的参考资料。但是,我得到的大多数信息都表明,每个REST请求都应该打开和关闭套接字。

到现在为止,我已经绝望了,准备考虑任何假设;-)

有人能说明在地址移动主机后继续将数据包路由到错误主机的机制吗?

在3到4分钟之后,我们又能说什么呢?这是什么类型的缓存。

谢谢大家的建议。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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)。

代码语言:javascript
复制
System.setProperty("http.keepAlive", "false");

这使得系统为每个HTTP请求打开一个新的套接字。你失去了效率,但得到了一个客户可以生存的地址移动。这在我的情况下是很关键的(但可能不是一个常见的情况)。

本文还提到了控制池(例如,它的大小)可以做的其他一些事情。

另一种方法可能是在地址交换机上发送一个HTTP头,并将元数据连接设置为关闭。要正确处理这个问题需要更多的技巧,但大多数时候都会保持客户端的有效性。

任何人有更多的见解,请随时提供。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22597621

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档