0

我正在开发一个具有某种实时更新的网站。现在该网站是使用数据集当前 ID 的 javascript 变量生成的。然后在几秒钟的时间间隔内,通过当前 ID 进行 AJAX 调用,如果有新的东西,服务器将其与最新的 ID 一起返回,然后在 javascript 中更新。很简单,但问题来了。

如果用户多次打开同一个页面,每个页面都会执行此 AJAX 请求,这会产生繁重的服务器负载。

现在我想到了以下方法:

该网站加载了当前时间戳和当前数据集 ID 的 javascript 变量。我想要的刷新间隔是例如 3 秒。

在网站中,间隔计数器每秒钟计数一次,并且每次时间戳达到(timestmap % 3===0)返回 true 的状态时,都会更新内容。该链接看起来像http://www.example.com/refresh.php?my-revision=123×tamp=123456

现在这应该确保每个浏览器窗口调用相同的 URL。然后我可以打开浏览器级缓存。

但我真的不喜欢这个解决方案。我宁愿在 Cookie 中添加另一层数据共享。这应该不是什么大问题,我可以将每个请求存储在一个由时间戳和数据修订命名的 cookie 中,TTL 为 10 秒左右,然后首先检查它的存在。

这些页面将同时执行请求。因此,浏览器缓存和 cookie 的整个逻辑可能无法正常工作,因为请求是同时发生的,而不是一个接一个。

所以我考虑将当前连接限制在 1 个服务器端。但是我至少需要一个额外的虚拟主机,因为我真的不想为整个页面这样做。这让我遇到了有关跨站点策略的问题!

当然,有一些超级复杂的负载平衡解决方案/服务器端解决方案必然会请求 uri 和 ip 地址或其他东西,但这都是极端的矫枉过正!

应该是通病!想想脸书聊天。我真的不认为他们会在您打开的每个窗口中完成所有请求...

有任何想法吗?我真的被这个困住了!

Maby 我可以做一些跨窗口的 Javascript 通信吗?如果它们都在同一个域上,应该不是问题吗?

我当然可以做的一件事是服务器端缓存。这至少避免了数据库连接和密集计算......但它仍然是我想避免的请求。

4

2 回答 2

2

您可能想查看CometOrbited。这最好通过服务器推送技术来解决。

于 2010-09-19T13:24:52.763 回答
1

第一件事是:无论如何都要进行服务器端缓存,使用MemcacheRedis或其他任何东西。因此,您可以抵御三台执行请求的机器。但你知道的。

坦率地说,我认为您使用 cookie 是正确的(但请参阅下面的更现代的选项) - 它们由所有窗口实例共享,易于查询等。您的轮询逻辑可能如下所示:

在轮询间隔上:

  • 查看内容 cookie:它比您拥有的更新鲜吗?如果是这样,使用它,你就完成了。
  • 查看状态cookie;是否有其他人主动轮询(例如,cookie 已设置且未过时)?如果是,请稍后再回来。
  • 设置状态cookie:我正在(现在)积极投票。
  • 做请求

回应:

  • 如果新数据比内容 cookie 的(可能更新的)内容更新,则将内容 cookie 设置为新数据
  • 如果您是设置它的人,请清除状态 cookie

基本上,状态 cookie 充当一个信号量,向所有窗口实例指示某人在某处正在更新内容。

您的内容 cookie 可能直接包含内容,或者如果您的内容很大并且您担心会遇到限制,您可以让每个页面都有一个隐藏的 iframe,每个页面都有一个唯一的名称,并让您的 Ajax 更新写入输出到 iframe。内容 cookie 将发布最新 iframe 的名称,其他看到有新内容的窗口可以window.open用来获取该 iframe(因为window.open如果您使用现有 iframe 的名称,则不会打开窗口) .

警惕比赛条件。尽管任何给定页面中的 JavaScript 都是单线程的(除非明确使用web workers),但您不能期望其他窗口中的 JavaScript 一定在同一线程上运行(它在某些浏览器上,而不是在其他浏览器上 - 见鬼,在 Chrome 上它甚至不是同一个过程)。我也不知道在编写 cookie 时有任何原子性保证,所以你要保持警惕。

现在,HTML5 定义了一些有用的文档间通信机制,因此您可能会考虑查看它们是否存在并在使用这种 cookie 方法之前使用它们,因为它们可以在今天的现代浏览器中工作,但不能在旧浏览器中使用。现在可能不得不处理。不过,在支持它的浏览器上,太棒了!

作为上述方面的一个方面, Web 存储也可能是一个值得研究的选项,但您的客户几乎肯定必须授予您的应用程序权限,这也是一个相当新的事物。

于 2010-09-19T13:42:52.953 回答