2

在 GAE 项目上工作,我们的一个要求是我们希望能够及时确定用户是否离开了应用程序。目前我们有这个工作,但不可靠,所以我正在研究替代方案。

我们现在这样做的方式是我们有一个函数设置在 JS 中运行,该函数使用 AJAX 调用向 GAE 应用程序发送心跳信号。这工作相对较好,但会产生大量流量和 CPU 使用率。如果我们在几分钟内没有听到客户的心跳,我们确定他们已经离开了应用程序。我们还连接了 unload 函数以发送部分消息,再次通过 AJAX 调用。这效果不太好,但大多数时候根本没有。

我们也在使用 Channels API。我注意到的一件事是,当我们的应用程序使用开放频道时,客户端似乎也在以调用http://talkgadget.google.com/talkgadget/dch/bind的形式发送心跳信号。我相信这是在客户端打开频道时加载的 iFrame 和/或 JS 发生的。

我的问题是,我在服务器端的应用程序能否连接到这些对http://talkgadget.google.com/talkgadget/dch/bind的调用并将其用作心跳信号?有没有更好的方法来检测客户端是否仍然连接,即使他们没有主动在客户端做任何事情?

4

4 回答 4

3

谷歌已添加此功能:

请参阅https://developers.google.com/appengine/docs/java/channel/overview

跟踪客户端连接和断开连接

当客户端连接到通道或从通道断开连接时,应用程序可能会注册以得到通知。

您可以在 appengine-web.xml 中启用此入站服务:

于 2013-04-11T04:37:38.137 回答
1

目前,通道 API 会预先向您收取通道将消耗两个小时的所有 CPU 时间,因此向死通道发送消息可能比向服务器发送一堆心跳消息更便宜。

https://groups.google.com/d/msg/google-appengine/sfPTgfbLR0M/yctHe4uU824J

我会尝试将“请确认”参数附加到每 N 条消息(错开以避免每个客户端确认单个消息)。如果忽略其中 2 个,则将通道静音,直到您收到该客户端的消息。

于 2011-03-23T22:34:18.307 回答
1

您目前无法使用 Channel API 来确定用户是否仍然在线。您目前的最佳选择取决于用户下线后立即了解的重要性。

如果您只是想知道他们处于离线状态以便您可以停止发送消息,或者您立即知道这并不重要,您可以简单地在常规交互中搭载 ping。每当您向客户端发送更新并且您有一段时间没有收到他们的任何消息时,请使用“ping 请求”标记消息,并让客户端在收到此类标记的消息时发送 HTTP ping。这样,您在向他们发送消息后不久就会知道他们已经消失了。您也不会施加很多额外的开销,因为如果您没有从他们那里听到任何其他信息,他们只需要发送明确的 ping。

如果您预计长时间不活动并且及时知道他们何时下线很重要,那么您必须按照您的建议让他们按计划发送 ping。您仍然可以使用在其他请求上捎带 ping 的技巧来最小化它们,并且您应该在可以管理的范围内设置 ping 之间的间隔,以减少负载。

于 2011-03-23T23:05:52.800 回答
1

对于您将客户端“连接”到服务器的核心问题,我没有很好的解决方案。但我确实对您当前的周期性 ping 的“流量和 CPU 使用率”问题有一个有趣的想法。

我假设你有一个预定义的心跳间隔时间,比如 1 分钟。因此,如果有 120 个客户端,您的服务器将以平均每秒 2 次的速度处理心跳。如果其中一半是“空闲客户”,那就不好了。

让我们假设客户端已经空闲了 15 分钟。此客户端浏览器是否仍需要以 1 分钟的恒定预定义间隔发送心跳?为什么不让它可变呢?

我的建议很简单:根据客户的活动水平改变心跳。

当客户端处于“活动状态”时,心跳以每分钟 1 次的速度工作。当客户端“不活动”超过 5 分钟时,心跳率会减慢到 50%(每 2 分钟一次)。再过 10 分钟,心跳率又下降了 50%(每 4 分钟 1 次)......在某个阈值点,将客户端视为“未连接”。

在这种方法中,“空闲客户端”不会因为频繁的心跳而困扰服务器,从而让您的应用服务器专注于“活动客户端”。

它有很多 javascript 要做,但如果您在流量和 CPU 使用方面遇到问题,可能值得:-)

于 2011-03-24T05:08:42.720 回答