28

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

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

我的目标是创建一个实时聊天应用程序;希望与 Django 相关联,用于用户、身份验证、模板等。

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

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

Twisted / Twisted Web 似乎很流行,但我不知道要集成它或我还需要什么(猜想我至少需要客户端 JS)。

如果我理解正确,Orbited基于Twisted 构建的,我还需要其他什么吗?

Gevent 和 Eventlet 是否与 Twisted 属于同一类别?我还需要他们多少?

Celery、RabbitMQ 或 Redis 之类的 KV 存储在哪里出现?我不太了解消息队列的概念。它们是必不可少的吗?它们提供什么服务?

有没有我应该看的完整的聊天应用教程?

我将完全感谢任何帮助我克服这个心理障碍的人,如果我遗漏了什么,请不要犹豫。我知道这是一个非常重要的问题。

4

3 回答 3

8

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

于 2011-04-11T00:30:21.563 回答
5

在过去的几个月里,我不得不经历同样的研究,我感受到了你的痛苦。我还没有时间处理适当的文档,但是我在http://bitbucket.org/virtualcommons/vcweb有一个使用 Django 与socket.iotorndio的工作示例- 我希望建立直接通信Django服务器端到使用队列的tornadio服务器进程(即,django视图中的逻辑将消息推送到队列中,然后由tornadio处理,将消息的json编码版本推送给所有感兴趣的订阅者)但还没有尚未完全实施该部分。我目前设置它的方式包括:

  1. 一个外部 tornado (tornadio) 服务器,在另一个端口上运行,接受 socket.io 请求并使用 Django 模型。此服务器进程对数据库的唯一写入是需要存储的聊天消息。它拥有对所有Django模型等的完全访问权限,所有实时交互都需要直接经过这个服务器进程。
  2. 需要实时访问的 Django 模板页面包括 socket.io javascript 并建立与 torndio 服务器的直接连接

我研究了orbitedhookboxgevent,但决定使用 socket.io + tornado,因为它似乎允许我使用最干净的 javascript + python 代码。不过,我可能错了,在过去的一年里刚刚开始学习 Python/Django。

于 2011-04-11T21:06:31.843 回答
3

Redis 作为一个持久层是相关的,它也支持本机发布/订阅。因此,您可以订阅频道并将消息推送给您,而不是轮询数据库以查找新消息的情况。

我找到了您描述的系统类型的工作示例。魔术发生在socketio 视图中:

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. 运行一个“发布者”,它从 socket.io(来自用户的浏览器)获取消息并将它们推送到 Redis
  4. 重复直到套接字断开

Redis Cookbook 提供了更多关于 Redis 方面的详细信息,并讨论了如何持久化消息。

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

Celery 是一个“分布式任务队列”——基本上,它可以让你将工作单元分散到多台机器上。“分布式”角度意味着机器之间需要某种运输。Celery 支持多种类型的传输,包括 RabbitMQ(以及 Redis)。

在您的示例的上下文中,只有当您必须对每条消息进行某种昂贵的处理(例如扫描脏话或其他内容)时,Celery 才适用。即便如此,仍然需要启动 Celery 任务,因此需要一些代码来监听 socket.io 回调。

(以防你不完全困惑,Celery 本身可以使用 Gevent 作为其底层并发库。)

希望有帮助!

于 2012-09-10T17:51:33.210 回答