【问题标题】:Pattern/Best practice for updating objects on server from multiple clients从多个客户端更新服务器上对象的模式/最佳实践
【发布时间】:2014-02-05 22:45:21
【问题描述】:

我有一个关于解决问题的最佳实践或模式的一般性问题。

假设您在不同的 JVM 上运行了三个程序:Server、Client1 和 Client2。

所有三个进程都对对象进行更改。当任一客户端中的对象发生更改时,必须将对象(不是新对象)中的更改发送到服务器。仅仅将新对象从客户端发送到服务器是不可能的,因为两个客户端可能同时更新对象,所以我们需要增量,而不是结果。

此时我并不担心将服务器上的更改反映给客户端,但让我们考虑一下这是一个额外的问题。

使用 X 数量的进程和 Y 数量的可能更改的对象类来实现这一点的最佳实践是什么?

我能想到的最好的方法是始终使用命令模式来同时更改客户端和服务器上的对象,但必须有更好的方法吗?

【问题讨论】:

  • 可用于此类问题的观察者设计模式
  • 是否可以通过网络使用观察者模式?通常我会看到观察者模式用于通知更改,而不是具体更改了什么?
  • 演员模型浮现在脑海,因为它已经是基于消息的。因此,将消息复制到其他服务器应该很容易。看看 Akka。

标签: java design-patterns


【解决方案1】:

解决这个问题的一种可能方法是Java 中的Remote Method Invocation 系统。将所有数据值保留在服务器上,然后让客户端使用远程调用来查询它们。

然而,这需要一些智能缓存来减少无意义的调用数量。最后你会得到类似于命令模式的东西。

现代游戏试图通过我称之为“执行-然后-验证”模式的方式来解决这个问题,在这种模式下,每个客户端都有一个游戏世界的本地副本,这使他能够对每个动作得出与服务器会。因此,假设玩家的动作是正确的,它们将应用于游戏世界的本地副本,然后将它们发送到服务器,这是接受或稍后撤销它的最终实例。

这种本地缓存变体的好处是,大多数玩家不会遇到太多延迟,但是在相互矛盾的动作的情况下,他们可能会遇到众所周知的回滚。

最终,这在很大程度上取决于您要做什么以及对您来说更重要的是:控制操作或客户端操作流程。

【讨论】:

  • 您会说执行-然后-验证模式,正如您所说的那样,在某种程度上等同于在本地副本和服务器副本上执行命令,然后轮询服务器以获取“实际”结果?
  • 有相似之处,但不同的是,服务器可以用简单的 ACK 响应或根本不向执行客户端发送任何数据,以保持开销尽可能低。它也可以将操作转发给其他客户,让他们自己决定将要发生的事情。在某些方面,服务器必须进行全面更新,但目标是尽可能少地保持这种情况。所以在这种情况下,服务器只是一个验证实例,而不是实际的参与者。
  • 所以客户端会发送一个更新,然后服务器会接受或拒绝它,然后客户端什么都不做,还是回滚?但是,如果另一个客户端进行了更改,服务器会直接将更改或整个对象发送给其他客户端吗?
  • 这取决于您的要求。在游戏世界中,许多动作都可以忽略不计,如果客户弄错了也没关系。如果您有业务控制软件,这可能是完全不同的情况。因此,您基本上可以将它们归类为关键更改和非关键更改。不重要的将被转发为“客户端 X 做了这个:......”,而关键的将包括世界的实际新状态。另外或多或少的频繁更新需要保证局部世界的误差不超过一定等级。
猜你喜欢
  • 2020-08-15
  • 2020-11-11
  • 2011-04-27
  • 1970-01-01
  • 1970-01-01
  • 2015-08-28
  • 2012-05-24
  • 1970-01-01
  • 2021-06-22
相关资源
最近更新 更多