8

如何在 facebookticker、meetup.com 主页等浏览器中显示持续的实时更新?在 python、PHP、node.js 中,服务器端的性能影响是什么?另外,如果页面由 akamai 之类的 CDN 缓存,我们如何实现相同的更新?

4

4 回答 4

18

您有两个选项(其他人在上面详细说明)。如果您不熟悉每个选项背后的一些概念性想法,我想我会给出一两行关于它们的信息。请注意,我在非常非常高的层次上介绍这些概念。

您的三个选项是:

  1. 短轮询
  2. 网络套接字
  3. 彗星/长轮询

短轮询

Short Polling通过强制客户端不断向服务器发送请求,克服了 Client-Server 之间的单向通信,形式如下:

Client: Do you have a message for me?
Server: No.
Client: (wait x seconds)
Client: Do you have a message for me?
Server: No.
Client: (wait x seconds)
Client: Do you have a message for me?
Server: Yes. Here it is!
Client: Yay!
Client: (update message)

代表客户的不断唠叨被称为轮询。为了实现这种结构,您需要将服务器设置为“监听”来自客户端的这些轮询请求。服务器还必须将这些消息存储在某个地方,以便在消息准备好时,服务器可以传递它们。在非常简单的级别上,您的服务器需要:

  • 接受一般网络请求
  • 接受轮询请求
  • 运行获取消息的后台作业
  • 将这些消息存储在某处,以便在轮询请求进入时,服务器可以检查它们。

您还需要将这些轮询请求与用户的某种会话 ID 联系起来,以便正确的消息到达正确的人。总体而言,范式很复杂,在我看来,效率低下。

网络套接字

Web Sockets 是 HTML5 的新功能。它们背后的基本思想是客户端可以保持与服务器的直接连接,并且它们可以相互推送信息。因此,与通常的做法不同:客户端发送 GET 请求>>服务器响应内容,Web Sockets 允许您保持持续对话。

但是,为了进行设置,您需要:

  • 与 WebSocket 兼容的浏览器(并非全部都是)。
  • 可以处理 Web 套接字的服务器(不确定如何表达这一点,但并非所有服务器都设置为这种安排)。

设置有点复杂,虽然比长轮询简单:

  • 客户端保持与服务器的启用 Web 套接字的连接的连接
  • 服务器通过 web socket 将结果推送给客户端
  • 客户端根据结果更新页面

您会看到这种称为推送通知的模式(当然,如果您拥有 iPhone,您会经历过这种情况),因为服务器已被授权向客户端推送“东西”(多么不礼貌!)。由于有很多客户端和服务器的细微差别,我建议测试一下Pusher之类的东西,它基本上是一个 Web 服务,用于处理 Web Sockets 的所有困难部分。在开始自己设置之前,这将是您测试和使用该模式的一种简单方法。它同时具有客户端和服务器端库。

希望这些信息为您提供解决问题的基准。其他答案包含有关如何解决每种情况的更直接信息。

彗星/长轮询

Web Sockets 的另一种看似跨浏览器的方法是长轮询(参见Comet)。在这种情况下,您的客户端建立与服务器的连接并将其挂起,等待数据被推回。这个设置有点复杂,但它确实代表了Short PollingWeb Sockets之间的中间立场。

于 2012-07-27T15:46:47.293 回答
6

我建议使用 SockJS 或 Socket.io 作为客户端 JavaScript 库来实现类似套接字的连接,然后在服务器端使用 Tornado 将任何状态更改发布到客户端。代码相当简单。

客户端代码取决于您选择的库。SockJS 或 SocketIO。或者,如果您只想直接使用 Websockets,这非常简单:

update_socket = new WebSocket("ws://my_server.com/listening_url");
update_socket.onmessage = function (evt) {
    $("#my_div").html(evt);
};

服务器端代码也很简单:

import tornado

class UpdateHandler(tornado.websocket.WebSocketHandler):

    def open(self):
        self.write_message('Hi client')
        # listen for some events that are occurring
        for message in function_that_generates_events():
            self.write(message) 

    def on_message(self, message):
        # Do something with incoming messages

    def on_close(self):
        # tidy up

app = tornado.web.Application(('r/listening_url',UpdateHandler))
app.listen(9000)
于 2012-07-27T13:13:49.460 回答
0

您可以使用轮询、长轮询或者如果您想要一个推送系统。最简单的就是民意调查。但是,所有解决方案都需要客户端编码。

性能影响取决于您的解决方案。最容易实施的是民意调查。一次短频率的轮询有效地执行一个请求,例如 100 毫秒或模拟实时。长轮询的影响较小,但它会在或多或少的时间内保持打开大量请求。

于 2012-07-27T13:10:57.813 回答
0

码头

Ajax 推送引擎

套接字.io

这些是实现 Comet 的方法

我会推荐使用 Node.js 实现的 Socket.io

因为它利用最佳可用连接方法

于 2012-07-27T13:12:32.470 回答