跨网络在java实例之间同步变量

Jul*_*oQc 5 java sockets

我在大学里有这个任务,他们要求我们将Java应用程序作为具有多个客户端的套接字服务器运行.客户端发送一个字符串,服务器以大写形式返回带有请求计数器的字符串.非常简单.

任何给定客户端发出的每个请求都在服务器端计算,并存储在每个客户端连接线程的静态变量中.这样每个客户端请求都会在服务器上全局递增计数器.这很好用.

现在,他们要求我们在网络上的不同计算机上运行该服务器的"备份"实例,以便在主服务器停止响应时,客户端连接到其中一个备份.那,我开始工作了.但计数器显然已重置,因为它是一个不同的服务器.

挑战在于主要和次要的请求计数器是相同的,因此如果主要响应10个请求,然后关闭,客户端切换到备份并发出请求,则备份服务器响应11.

这是我考虑的:

  1. 如果在同一台PC上,我会使用线程,但我们在网络上,所以我相信这不会起作用.
  2. 服务器使用响应将该计数器发送到客户端,然后响应在下一次请求时将其返回给服务器,依此类推.不是非常"干净"的imo但可以工作.
  3. 每个服务器相互通信以同步此计数器.但是,即使可能,套接字似乎也不是非常有效.RMI似乎是替代方案,但在开始学习之前我想要确认.

这里有任何线索或建议吗?我没有发布代码,因为我不需要这里的解决方案,但如果有必要,我可以邀请到gihub回购.

编辑:此项目没有延迟,可靠性或类似约束.有X个客户端和Y个服务器(单个主服务器,多个故障转移).像DB这样的其他第三方基础设施实际上不是一种选择,但欢迎使用第三方Java库.基本上我只是在多台PC上运行Eclipse.这是对分布式系统的介绍,预计在2周内完成,因此我认为"保持简单"是关键!

编辑2:备份服务器的数量和地址将作为参数传递给应用程序,因此不需要广播/发现.我们可能会在学期后期的实验作业中涵盖所有这些要点:)

编辑3:从你所有的好建议,我将尝试实现#3的一些变体,让你知道它是如何工作的.我认为我在这里遇到的问题是确保所有服务器都知道其他服务器.但就像我提到的那样,他们不需要发现彼此,所以我现在将硬编码,并在下一个任务中重新访问!可能选择一些当选的主人...... :)

Tre*_*man 2

如果允许选项#2,那么它是最简单的,但是我不确定它在面对多个客户端时如何工作(所以这取决于这里的要求)。

是否可以通过在另一台计算机上运行的共享数据库来支持服务器?理想情况下,也许一个集群跨多台机器?或者您可以使用事件总线或第 3 方库/代码(共享缓存、JMS 甚至 EJB)?

如果没有,那么让服务器相互通信是最好的选择。套接字可以工作,UDP 多播也可以(但要小心,无法知道是否丢失了消息,这就是 TCP/套接字更安全的原因)。如果节点要相互通信,通常有几种可接受的方法来处理设置:

  • 主/从:当前节点是主节点,所有写入都针对该节点。从站连接到主站并接收更新。当主节点宕机时,需要选举一个新的主节点(参见领导者选举)。MongoDB 是这样工作的。
  • 每个人对每个人:每个节点都连接到每个其他已知节点。可能会变得复杂,并且可能无法很好地扩展到大量节点。
  • 菊花链:一个节点连接到下一个节点,下一个节点连接到下一个节点,依此类推。我不相信这会被广泛使用。
  • 环形网络:每个节点连接到另外两个节点以形成环。这通常优于菊花链,但实现起来稍微复杂一些。

请参阅此处了解更多示例: https: //en.wikipedia.org/wiki/Network_topology

如果这是在现实世界中(即不是学校),您将使用共享缓存(例如 ehcache)、由事件总线(某种 JMS)支持的本地缓存或共享集群数据库。


编辑:

重新阅读您的问题后,您似乎只需要担心一个备份服务器,我对课程要求的猜测是,他们只是希望您的备份服务器连接到主服务器并接收变量计数更新。这完全可以通过套接字实现(对于单个备份服务器来说效率并不低),并且可能是他们期望您使用的解决方案。

例如,备份服务器连接到主服务器,并通过保持的连接轮询更新或简单地侦听从主服务器发出的更新。

要点: - 您可能需要保持活动状态以确保连接不会被终止。- 如果从备份到主设备的连接中断,请确保实现重新连接逻辑。

如果这是一个网络课程,他们可能期望 UDP 多播,但这可能有点取决于服务器/网络环境。