轻量级通知技术

时间:2011-09-18 07:41:31

标签: python django rabbitmq celery greenlets

我需要在django中开发一个实时的最近活动源(使用AJAX长轮询),我想知道什么是服务器端的最佳策略。

伪代码:

def recent_activity_post_save():
    notify_view()

[in the view]
while not new_activity():
    sleep(1)
return HttpResponse(new_activity())

首先要记住的是每秒查询数据库。不可行。其他选择:

  1. 使用缓存作为通知服务
  2. 使用像Celery这样的专业工具(我宁愿不这样做,因为它看起来有点矫枉过正)
  3. 最好的方式是什么?

8 个答案:

答案 0 :(得分:5)

我建议保持简单......

创建一个数据库表来存储你的事件,在适当的时候插入到那个表中,然后实现一个简单的ajax轮询技术,在客户端的每个 x 秒点击服务器。

考虑使用推送通知方法或使用noSql数据存储,我对其他解决方案感到担忧。它比使用Django框架内置的工具的传统拉动通知系统复杂得多,除了非常罕见的例外,它是过度的。除非您特别需要严格的实时解决方案,否则请保持简单并使用框架中已存在的工具,对于基于数据库或网络性能的反对者,我不得不说的是,过早优化是根本原因。万恶之物。

构建一个包含特定于您的应用程序的最新活动数据的模型,然后,只要您的应用程序执行了应该记录您可以插入此表的新活动的内容。

您的视图就像任何其他视图一样,从此RecentActivity表中拉出顶部 x 行(可选择基于查询参数等)。

然后,在客户端,你只需要一个简单的ajax轮询器,每隔 x 秒就能看到你的视图。您可以使用复杂的插件和技术,但编写自己的插件和技术并不复杂:

function simplePoll() {
  $.get("your-url", {query-parameters}, function(data){
    //do stuff with the data, replacing a div or updating json or whatever
    setTimeout(simplePoll, delay);
  });
}

我的观点是,在您的网站成功完成问题之前,性能问题并不是真正的问题。传统的关系数据库可以很好地扩展,直到你开始达到Twitter,谷歌等成功的水平。我们大多数人都没有达到这个水平:)

答案 1 :(得分:2)

您是否考虑使用信号?您可以在recent_activity_post_save()中发送信号,并且可能有一个侦听器将信息存储在缓存中。

视图只会引用缓存以查看是否有新通知。当然你不需要信号,但恕我直言,它会更加清洁,因为你可以添加更多“通知处理程序”。

这似乎是最佳的,因为您不需要轮询数据库(人工负载),通知几乎立即“可见”(仅在处理信号和与缓存交互所需的时间之后)。

所以伪代码看起来像这样:

# model
def recent_activity_post_save():
    post_save_signal.send()

# listener
def my_handler( ... ):
    cache.set( 'notification', .... )

post_save_signal.connect( my_handler )

# view
def my_view( request ):
    new_notification = None
    while not new_notification:
        sleep(1)
        new_notification = cache.get( 'notification' )
    return HttpResponse(...)

答案 2 :(得分:1)

您可以使用彗星解决方案,例如Ape project。这种项目旨在将实时数据发送到浏览器,并可以利用现代浏览器的Web套接字功能。

答案 3 :(得分:0)

您可以使用触发器(每当发布新帖子时都会触发)。例如,此触发器可以在轮询目录中写入一个新文件,其中包含必要的数据(比如主键)。然后,您的python可以只查看该文件夹以获取新文件,而不必触摸数据库,直到出现新文件。

答案 4 :(得分:0)

如果你正在使用彗星解决方案,那么you could use orbited。让我警告你,因为它是一个相当小的解决方案,很难找到关于如何在生产环境中部署和使用orbited的好文档。

答案 5 :(得分:0)

以下是类似的讨论,从服务器端的角度回答:Making moves w/ websockets and python / django ( / twisted? ) ,最重要的答案是this one

还有this answer,指出了从Django尝试这个的非常可靠的替代方案。

如果您真的希望从现有的Django应用程序中提供此服务,请不要执行此服务器端。将HTTP套接字人质保存到单个浏览器的连接是破坏应用程序的快速方法。两个合理的选择是:探索各种Web套接字选项(如上面使用Pyramid托管服务的选项),或者让浏览器定期向服务器发送轮询请求以查找更新。

答案 6 :(得分:0)

您应该决定是否愿意采用“拉动”或“推送”架构来传递消息,请参阅此post on quora!如果你想找到一个将通知“推送”到接收器的解决方案,那么基于缓存/ nosql的系统是首选的,因为它们不会为很多写操作产生如此高的负载。

Redis例如具有已排序的集/列表数据结构,为您提供了大量实例。见例如。得到一个想法this post(虽然它不是python)。您还可以查看“真实”的消息队列,例如RabbitMQ

对于客户端连接,此处的其他帖子应该已经为您提供了有关如何使用扭曲和类似框架的一些想法。

芹菜可以永远是一个很好的工具,例如,你可以。在异步作业中写下用户的活动流!

答案 7 :(得分:0)

如果没有必要,我认为没有必要限制使用长轮询。编写库以利用可能的最佳选项(可能是短轮询,长轮询,websockets甚至是微小的flash插件,如果之前的选项都不可用)。 Node.js有一个最好的库用于这样的工作,称为Socket.IO,但幸运的是还有两个Python实现可用,gevent-socketiotornadio,但后来建立在龙卷风框架,所以可能无从谈起。

如果这适合您,您可以将它们与一些NoSQL(文档)数据库结合使用,该数据库被证明比关系数据库更快,更轻便。有许多选项,包括CouchDB,MongoDB,Redis,...... Socket.IO和基于文档的数据库的组合已被证明是快速,轻量和可靠的。

虽然我已经看到你在评论中已经考虑过NoSQL,但我个人认为,如果你需要一个快速简便的解决方案,以及适合你的选项,这是你可能采取的最佳机会。

相关问题