11

我需要在 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(我不想这样做,因为它看起来有点矫枉过正)

去这里的最佳方式是什么?

4

8 回答 8

5

我建议保持简单...

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

我对考虑使用推送通知方法或使用 noSql 数据存储的其他解决方案感到担忧。它比使用 Django 框架中内置的工具的传统拉式通知系统复杂得多,而且除了极少数的例外情况外,都是多余的。除非你特别要求严格的实时解决方案,保持简单,使用框架中已经存在的工具,而对于基于数据库或网络性能有异议的人,我只能说,过早的优化是问题的根源。一切邪恶。

构建一个包含特定于您的应用程序的最近活动数据的模型,然后,每当您的应用程序执行一些应该记录新活动的操作时,您都可以将其插入此表中。

您的视图将与任何其他视图一样,从该表中提取前xRecentActivity(可选地基于查询参数等)。

然后,在客户端,您只需有一个简单的 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、Google 等成功的水平。我们大多数人都没有达到那个水平 :)

于 2011-10-02T19:08:22.327 回答
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(...)
于 2011-09-28T14:08:55.083 回答
1

您可以使用彗星解决方案,例如Ape 项目。此类项目旨在向浏览器发送实时数据,并可以利用现代浏览器的 web sockets 功能。

于 2011-09-18T08:28:28.540 回答
0

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

于 2011-09-18T08:18:54.693 回答
0

如果不是真的需要,我认为没有必要限制自己使用长轮询。编写了一些库以利用可能的最佳选项(如果以前的选项都不可用,可能是短轮询、长轮询、websockets 甚至是微型闪存插件)。Node.js 拥有最适合此类工作的库之一,称为 Socket.IO,但幸运的是还有两个 Python 实现可用,gevent-socketiotornado,但后来构建在 tornado 框架之上,所以可能会出局的问题。

如果这适合您,您可以将它们与一些 NoSQL(文档)数据库结合起来,事实证明,它比关系数据库更快、更轻量级。有很多选择,包括 CouchDB、MongoDB、Redis,...... Socket.IO 和基于文档的 DB 的组合已被证明是快速、轻量级和可靠的。

虽然我看到你已经在评论中考虑过 NoSQL,但我个人的看法是,如果你需要一个快速简单的解决方案,并且上面的选项适合你,那么这是你最好的机会。

于 2011-10-02T17:50:16.923 回答
0

这是一个类似的讨论,从服务器端的角度回答:Making move w/websockets and python / django (/twisted?) ,最重要的答案是这个

还有这个答案,指向一个非常可靠的替代方案,可以从 Django 尝试这个。

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

于 2011-09-27T02:52:24.653 回答
0

您应该决定是否更愿意使用“拉”或“推”架构来传递您的消息,请参阅quora 上的这篇文章!如果您想寻求一种解决方案,将通知“推送”到他们的接收者,基于缓存/nosql 的系统是可取的,因为它们不会为大量写入操作产生如此高的负载。

例如,Redis 及其排序的集合/列表数据结构为您提供了很多实例。参见例如。这篇文章(虽然它不是python)来了解一下。例如,您还可以查看像RabbitMQ这样的“真实”消息队列!

对于客户端连接,这里的其他帖子应该已经给你一些关于如何使用扭曲和类似框架的想法。

Celery 总是一个很好的工具,你可以。在异步作业中将所有写入用户的活动流!

于 2011-09-30T21:23:38.823 回答
0

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

于 2011-09-26T23:57:18.047 回答