具有并发用户和繁重数据处理的交互式webapp架构

时间:2012-08-25 10:41:18

标签: python django multithreading architecture twisted

我遇到了一个特定的问题并想到了一个解决方案。但由于解决方案非常复杂,我想知道其他人是否遇到过类似的问题,并且可以评论最佳做法或提出替代方案。

问题如下: 我有一个用Django编写的webapp,它有一些屏幕,其中来自多个表的数据以时间间隔被收集,分组和聚合。 它基本上是一个很好的矩阵,我们在一个轴上以时间间隔汇总数据,而另一个轴上每个时间间隔的聚合数据资源。 它涉及许多内部和左侧连接以收集所有数据,并且由于“报告”类似于所呈现数据的特征,我使用原始sql一起查询所有内容。

问题是多个用户可以同时查看&以这些间隔编辑数据。与使用相同数据但处于子/重叠间隔的其他用户相比,他们还可以编辑更精细或更粗粒度的数据。目前,当用户编辑某些数据时,会触发django请求,更改数据,聚合受影响的间隔。再次分组并呈现回来。但是由于这些数据的易变性,其他用户可能在他们面前改变了一些东西。每次分组/聚合和重新呈现表是非常繁重的操作(取决于数据量和间隔的范围)。并发用户编辑时会变得更糟..

我建议的解决方案: 很明显,http请求/响应机制对于这种事情并不是很理想;分组/聚合是非常重要的,对于每个请求来说并不理想,并发性最好是在用户之间传递,反馈应该是实时的,如googledocs而不是整页刷新。

我正在考虑制作一个守护程序进程,该进程根据请求从dbms读取感兴趣的 flat 数据并将其缓存在内存中。然后,对数据的所有更改都将在内存中进行,并对dbms进行直写。此守护程序通过锁定通道访问数据,因此守护程序可以处理哪些用户可以覆盖其他更改。

使用python代码聚合和分组平面数据,并且仅返回用户所需的切片;用户/守护进程通信将在websockets上运行。守护程序将提供订阅者/发布者通道,其中对特定数据片段感兴趣的用户在发生更改时得到通知。这个守护进程可以使用像twisted这样的框架来实现。但是我不确定事件驱动的方法在这里会起作用,因为我们想要“引导”所有的请求......也许这些应该放在一个队列中并在一个单独的线程中运行?在我的调度程序旁边的线程中进行扭曲运行会更好吗,或者扭曲的主循环是否应该关闭在此队列上运行的线程?我的理解是,线程最适合IO,而python重码基本上阻止了其他线程。我有两个(websockets / dbms和处理数据),这会起作用吗?

以前有人做过类似的事吗?

提前致谢!

卡尔

2 个答案:

答案 0 :(得分:3)

Google针对现已放弃的Wave产品的并发编辑功能实施的方案已记录在案http://www.waveprotocol.org/whitepapers/operational-transform。 Wave的这个方面似乎是成功的,尽管Wave本身很快就被抛弃了。

就您提出的有关实施拟议方案的问题而言:

  1. 事件驱动系统完全能够实现这一想法。事件驱动是组织代码的一种方式。它不会阻止您实现任何特定功能。
  2. 线程不是最好用,特别是在Python中。
    1. 由于CPython一次只运行一个Python线程(无论可用的硬件资源如何),因此它对CPU绑定工作具有明显的缺点。这意味着多线程CPU绑定的Python程序通常不会比单线程等效程序更快,甚至更慢。
    2. 对于IO,这个缺点不是限制,因为IO不涉及在CPython上运行Python代码(IO API都是用C实现的)。这意味着您可以同时在多个线程中执行IO,因此线程可能是一个好处。但是,在单个线程中同时执行IO正是Twisted的用途。只要您在非阻塞地(或者可能是异步地)执行IO,线程就不会比在单个线程中执行IO有任何好处。
  3. Hello world。

答案 1 :(得分:2)

我尝试了类似的东西,你可能对解决方案感兴趣。这是我的问题:

python Socket.IO client for sending broadcast messages to TornadIO2 server

这就是答案:

https://stackoverflow.com/a/10950702/675065

他还写了一篇关于解决方案的博客文章:

http://blog.y3xz.com/blog/2012/06/08/a-modern-python-stack-for-a-real-time-web-application/

软件堆栈包括:

我自己实现了它,它就像一个魅力。