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

发布于 2024-10-31 11:28:22 字数 851 浏览 7 评论 0原文

在花了整整两天时间之后,我仍然发现不可能理解 Python 中 Comet 的所有选择和配置。我已经阅读了这里的所有答案以及我能找到的每一篇博客文章。此刻感觉我快要出血了,所以我对这个问题的任何错误表示最诚挚的歉意。

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

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

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

首先,有人可以对这项工作所需的所有工具进行分类吗?
我读过有关不同服务器、网络库、引擎、客户端 JavaScript 的内容,但我不知道还有什么。我从没想过事情会如此复杂。

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

如果我理解正确的话,Orbited 是在 Twisted 上构建的,我还需要其他东西吗?

Gevent 和 Eventlet 与 Twisted 属于同一类别吗?我还需要他们做什么?

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

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

我将非常感谢任何帮助我克服这个心理障碍的人,如果我遗漏了什么,请随时询问。我知道这是一个很沉重的问题。

After spending two entire days on this I'm still finding it impossible to understand all the choices and configurations for Comet in Python. I've read all the answers here as well as every blog post I could find. It feels like I'm about to hemorrhage at this point, so my utmost apologies for anything wrong with this question.

I'm entirely new to all of this, all I've done before were simple non-real-time sites with a PHP/Django backend on Apache.

My goal is to create a real-time chat application; hopefully tied to Django for users, auth, templates, etc.

Every time I read about a tool it says I need another tool on top of it, it feels like a never-ending chain.

First of all, can anybody categorize all the tools needed for this job?
I've read about different servers, networking libraries, engines, JavaScripts for the client side, and I don't know what else. I never imagined it would be this complex.

Twisted / Twisted Web seems to be popular, but I have no idea to to integrate it or what else I need (guessing I need client-side JS at least).

If I understand correctly, Orbited is built on Twisted, do I need anything else with it?

Are Gevent and Eventlet in the same category as Twisted? How much else do I need with them?

Where do things like Celery, RabbitMQ, or KV stores like Redis come into this? I don't really understand the concept of a message queue. Are they essential and what service do they provide?

Are there any complete chat app tutorials I should look at?

I'll be entirely indebted to anybody who helps me past this mental roadblock, and if I left anything out please don't hesitate to ask. I know it's a pretty loaded question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

青春有你 2024-11-07 11:28:22

您可以使用 Socket.IO。有gevent 和tornado 处理程序。请参阅我关于 Django 的 gevent-socketio 的博客文章: http:// /codysoyland.com/2011/feb/6/evented-django-part-one-socketio-and-gevent/

You could use Socket.IO. There are gevent and tornado handlers for it. See my blog post on gevent-socketio with Django here: http://codysoyland.com/2011/feb/6/evented-django-part-one-socketio-and-gevent/

风蛊 2024-11-07 11:28:22

我感受到你的痛苦,因为在过去的几个月里不得不进行同样的研究。我还没有时间处理适当的文档,但我有一个使用 Django 与 socket.io 和 < a href="https://github.com/MrJoes/tornadio" rel="noreferrer">tornadio 位于 http://bitbucket.org/virtualcommons/vcweb - 我希望使用队列建立从 Django 服务器端到tornadio 服务器进程的直接通信(即,django 视图中的逻辑将消息推送到然后由 Tornadio 处理的队列,该队列将该消息的 json 编码版本推送给所有感兴趣的订阅者),但尚未完全实现该部分。我目前的设置方式包括:

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

我研究过的tornadio服务器建立直接连接orbitedhookboxgevent< /a> 但决定使用 socket.io + 龙卷风,因为它似乎可以让我得到最干净的 javascript + python 代码。不过,我的想法可能是错的,因为我在过去的一年里才开始学习 Python/Django。

I feel your pain, having had to go through the same research over the past few months. I haven't had time to deal with proper documentation yet but I have a working example of using Django with socket.io and tornadio at http://bitbucket.org/virtualcommons/vcweb - I was hoping to set up direct communication from the Django server-side to the tornadio server process using queues (i.e., logic in a django view pushes a message onto a queue that then gets handled by tornadio which pushes a json encoded version of that message out to all interested subscribers) but haven't implemented that part fully yet. The way I've currently gotten it set up involves:

  1. An external tornado (tornadio) server, running on another port, accepting socket.io requests and working with Django models. The only writes this server process makes to the database are the chat messages that need to be stored. It has full access to all Django models, etc., and all real-time interactions need to go directly through this server process.
  2. Django template pages that require real-time access include the socket.io javascript and establish direct connections to the tornadio server

I looked into orbited, hookbox, and gevent but decided to go with socket.io + tornado as it seemed to allow me the cleanest javascript + python code. I could be wrong about that though, having just started to learn Python/Django over the past year.

强辩 2024-11-07 11:28:22

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 作为其底层并发库。)

希望有所帮助!

Redis is relevant as a persistence layer that also supports native publish/subscribe. So instead of a situation where you are polling the db looking for new messages, you can subscribe to a channel, and have messages pushed out to you.

I found a working example of the type of system you describe. The magic happens in the 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()

Take the view step-by-step:

  1. Set up socket.io, get a redis client and the current user
  2. Use Gevent to register a "subscriber" - this takes incoming messages from Redis and forwards them on to the client browser.
  3. Run a "publisher" which takes messages from socket.io (from the user's browser) and pushes them into Redis
  4. Repeat until the socket disconnects

The Redis Cookbook gives a little more detail on the Redis side, as well as discussing how you can persist messages.

Regarding the rest of your question: Twisted is an event-based networking library, it could be considered an alternative to Gevent in this application. It's powerful and difficult to debug in my experience.

Celery is a "distributed task queue" - basically, it lets you spread units of work out across multiple machines. The "distributed" angle means some sort of transport is required between the machines. Celery supports several types of transport, including RabbitMQ (and Redis too).

In the context of your example, Celery would only be appropriate if you had to do some sort of costly processing on each message like scanning for profanity or something. Even still, something would have to initiate the Celery task, so there would need to be some code listening for the socket.io callback.

(Just in case you weren't totally confused, Celery itself can be made to use Gevent as its underlying concurrency library.)

Hope that helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文