需要帮助理解Python中的Comet(使用Django)

时间:2011-04-10 19:49:23

标签: python django twisted comet gevent

花了整整两天的时间后,我仍然发现无法理解Comet in Python的所有选择和配置。我已经阅读了这里的所有答案以及我能找到的每篇博文。感觉就像我现在要出血一样,所以我对这个问题的任何错误都表示歉意。

我对这一切都是全新的,我之前所做的只是在Apache上使用PHP / Django后端的简单非实时站点。

我的目标是创建一个实时聊天应用程序;希望绑定到Django用户,身份验证,模板等

每当我读到一个工具时,它说我需要另一个工具,它感觉就像一个永无止境的链。

首先,任何人都可以对这项工作所需的所有工具进行分类吗? 我已经阅读了有关客户端的不同服务器,网络库,引擎,JavaScripts,我不知道还有什么。我从没想过会是这么复杂。

Twisted / Twisted Web似乎很受欢迎,但我不知道要整合它或我还需要什么(猜测我至少需要客户端JS)。

如果我理解正确,Orbited在上构建 Twisted,我还需要其他任何内容吗?

Gevent和Eventlet与Twisted属于同一类吗?我还需要多少钱呢?

Celery,RabbitMQ或像Redis这样的KV商店在哪里出现?我真的不明白消息队列的概念。它们是否必不可少,它们提供的服务是什么?

我应该看一下完整的聊天应用教程吗?

我会完全感激任何帮助我度过这个精神障碍的人,如果我遗漏了任何东西,请不要犹豫。我知道这是一个非常有问题的问题。

3 个答案:

答案 0 :(得分:8)

你可以使用Socket.IO。它有gevent和龙卷风处理程序。在这里查看关于Django的gevent-socketio的博客文章:http://codysoyland.com/2011/feb/6/evented-django-part-one-socketio-and-gevent/

答案 1 :(得分:5)

我感到很痛苦,过去几个月不得不经历同样的研究。我还没来得及处理正确的文档,但我有一个在socket.io使用Django与tornadiohttp://bitbucket.org/virtualcommons/vcweb的工作示例 - 我希望建立直接通信使用队列的Django服务器端到龙卷风服务器进程(即,django视图中的逻辑将消息推送到队列,然后由tornadio处理,该消息将该消息的json编码版本推送给所有感兴趣的订户)但是没有完全实现了那部分。我目前设置的方式涉及:

  1. 一个external tornado (tornadio) server,在另一个端口上运行,接受socket.io请求并使用Django模型。此服务器进程对数据库的唯一写入是需要存储的聊天消息。它可以完全访问所有Django模型等,并且所有实时交互都需要直接通过此服务器进程。
  2. 需要实时访问的Django模板页面包括socket.io javascript并建立与tornadio服务器的直接连接
  3. 我查看了orbitedhookboxgevent,但决定使用socket.io + tornado,因为它似乎允许我使用最干净的javascript + python代码。我可能错了,但在过去一年刚刚开始学习Python / Django。

答案 2 :(得分:3)

Redis与持久层相关,也支持原生publish/subscribe。因此,您可以订阅某个频道,并将消息推送给您,而不是轮询数据库查找新消息的情况。

我找到了您描述的系统类型的working example。魔术发生在socketio view

def socketio(request):
    """The socket.io view."""
    io = request.environ['socketio']
    redis_sub = redis_client().pubsub()
    user = username(request.user)

    # Subscribe to incoming pubsub messages from redis.
    def subscriber(io):
        redis_sub.subscribe(room_channel())
        redis_client().publish(room_channel(), user + ' connected.')
        while io.connected():
            for message in redis_sub.listen():
                if message['type'] == 'message':
                    io.send(message['data'])
    greenlet = Greenlet.spawn(subscriber, io)

    # Listen to incoming messages from client.
    while io.connected():
        message = io.recv()
        if message:
            redis_client().publish(room_channel(), user + ': ' + message[0])

    # Disconnected. Publish disconnect message and kill subscriber greenlet.
    redis_client().publish(room_channel(), user + ' disconnected')
    greenlet.throw(Greenlet.GreenletExit)

    return HttpResponse()

逐步观看视图:

  1. 设置socket.io,获取redis客户端和当前用户
  2. 使用Gevent注册“订阅者” - 这会从Redis接收传入的消息并将其转发到客户端浏览器。
  3. 运行“publisher”,它从socket.io(从用户的浏览器)获取消息并将其推送到Redis
  4. 重复直到套接字断开连接
  5. Redis Cookbook在Redis方面提供little more detail,并讨论如何保留消息。

    关于你的其余问题:Twisted是一个基于事件的网络库,它可以被认为是这个应用程序中Gevent的替代品。根据我的经验,调试功能强大且困难。

    Celery是一个“分布式任务队列” - 基本上,它允许您跨多台计算机分配工作单元。 “分布式”角度意味着机器之间需要某种运输。 Celery支持多种类型的传输,包括RabbitMQ(以及Redis)。

    在您的示例中,Celery仅适用于您必须对每条消息执行某种代价高昂的处理,例如扫描亵渎或其他内容。即便如此,仍然需要启动Celery任务,因此需要一些代码来监听socket.io回调。

    (以防万一你没有完全混淆,Celery本身可以使用Gevent作为它的底层并发库。)

    希望有所帮助!