创建一个监听 redis pubsub 发布消息的 web url

发布于 2024-12-10 05:17:19 字数 2026 浏览 0 评论 0原文

编辑 好的,我有一个来自 javascript 的长轮询,与 django 视图对话。视图如下所示。它丢失了我从频道中的 Redis 客户端发布的一些消息。另外我不应该为每个请求连接到redis(也许redis变量可以保存在会话中?) 如果有人能指出我需要进行哪些更改才能使此视图与长轮询配合使用,那就太棒了!谢谢你!

    def listen (request):
        if request.session:
            logger.info( 'request session: %s' %(request.session))
        channel = request.GET.get('channel', None)
        if channel:
            logger.info('not in cache - first time - constructing redis object')
            r = redis.Redis(host='localhost', port=6379, db=0)
            p = r.pubsub()
            logger.info('subscribing to channel: %s' %(channel))
            p.psubscribe(channel)
            logger.info('subscribed to channel: %s' %(channel))
            message =  p.listen().next()
            logger.info('got msg %s' %(message))

            return HttpResponse(json.dumps(message));

        return HttpResponse('')

----原问题---- 我正在尝试创建一个聊天应用程序(使用 django、python)并试图避免轮询机制。我现在一直在努力解决这个问题 - 所以任何指示将不胜感激!

由于大多数浏览器不支持网络套接字,因此我认为长轮询是正确的选择。现在我正在寻找比常规轮询更好的扩展性并且易于与 python django 堆栈集成的东西。完成此开发后,我计划评估想到的其他 python 框架(tornado twinser、gevent 等)。

我做了一些研究,喜欢 redis 的 pubsub 机制。聊天消息被发布到两个用户都已订阅的频道。以下是我的问题:

  1. 据我了解,apache 无法很好地扩展,因为长轮询很快就会遇到进程/线程限制。因此我决定改用nginx。这个道理正确吗?另外,nginx 是否存在我担心的问题?特别是,我担心最新版本不支持 http 1.1 进行代理传递,正如博客文章 http://www.letseehere.com/reverse-proxy-web-sockets?

  2. 如何在浏览器端创建消息订阅的客户端部分?在我看来,这将是一个 javascript 代码将“长轮询”的 URL。因此,在 javascript 级别,客户端会轮询一个在服务器端以“非阻塞方式”被“阻止”的 url。当结果(在本例中是新的聊天消息)出现时,服务器返回结果。 JavaScript 执行它需要的操作,然后再次轮询相同的 url。这种想法正确吗?当 javascript 循环暂停时,在间隔之间会发生什么 - 我们是否会丢失来自服务器端的任何消息。

本质上,我想创建以下内容:

  1. 从redis,我向通道“foo”发布一条消息(也可以使用redis-cli - 稍后可以轻松地将其合并到python/django中)

  2. 我希望相同的消息出现在使用相同 js 代码的两个浏览器窗口中轮询。假设浏览器代码知道用于测试目的的通道名称

  3. 我发布第二条消息,该消息再次出现在两个浏览器窗口中。

我是实时应用程序的新手,因此对于任何可能没有意义的问题表示歉意。

谢谢你!

Edit
OK I have a long polling from javascript that talks to a django view. The view looks as follows. It loses some messages that I publish from redis client in the channel. Also I should not be connecting to redis for every request (Perhaps the redis variables can be saved in session?)
If someone can point out the changes I need to make this view work with long polling, it would be awesome! Thank you!

    def listen (request):
        if request.session:
            logger.info( 'request session: %s' %(request.session))
        channel = request.GET.get('channel', None)
        if channel:
            logger.info('not in cache - first time - constructing redis object')
            r = redis.Redis(host='localhost', port=6379, db=0)
            p = r.pubsub()
            logger.info('subscribing to channel: %s' %(channel))
            p.psubscribe(channel)
            logger.info('subscribed to channel: %s' %(channel))
            message =  p.listen().next()
            logger.info('got msg %s' %(message))

            return HttpResponse(json.dumps(message));

        return HttpResponse('')

----Original question---
I am trying to create a chat application (using django, python) and am trying to avoid the polling mechanism. I have been struggling with this now - so any pointers would be really appreciated!

Since web sockets are not supported in most browsers, I think long polling is the right choice. Right now I am looking for something that scales better than regular polling and is easy to integrate with python django stack. Once I am done with this development, I plan to evaluate other python frameworks (tornado twister, gevent etc.) come to mind.

I did some research and liked the redis pubsub mechanism. The chat message gets published to a channel to which both users have already subscribed to. Following are my questions:

  1. From what I understand, apache would not scale well since long polling would soon run into process/thread limits. Hence I have decided to switch to nginx. Is this rationale correct? Also are there any issues involved in nginx that I am worried about? In particular, I am worried about the latest version not supporting http 1.1 for proxy passing as mentioned in the blog post at http://www.letseehere.com/reverse-proxy-web-sockets?

  2. How do I create the client portion of the subscription of messages on the browser side? In my mind, it would be a url to which the javascript code would "long poll". So at the javascript level, the client would poll a url which gets "blocked" in a "non blocking way" at the server side. When a result (in this case a new chat message) appears, server returns the result. Javascript does what it needs to and then again polls the same url. Is this thinking correct? What happens in between the intervals when the javascript loop is pausing - do we loose any messages from the server side.

In essence, I want to create the following:

  1. From redis, I publish a message to a channel "foo" (can use redis-cli also - easy to incorporate it later in python/django)

  2. I want the same message to appear in two browser windows that use the same js code to poll. Assume that the browser code knows the channel name for test purpose

  3. I publish a second message that again appears in two browser windows.

I am new to real time apps, so apologies for any question that may not make sense.

Thank you!

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

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

发布评论

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

评论(1

且行且努力 2024-12-17 05:17:19

好吧,只是部分回答你的问题,并提到众多选项中的一个: Gunicorn 与异步工作类一起使用是一种解决方案长轮询/非阻塞请求非常容易设置!

Well just answering your question partly and mentioning one option out of many: Gunicorn being used with an async worker class is a solution for long-polling/non-blocking requests that is really easy to setup!

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