2008-12-01 110 views
6

我在写一个相当复杂的Web应用程序。 Python后端运行一种算法,其状态取决于存储在不经常改变的多个相关数据库表中的数据,以及经常改变的用户特定数据。当用户使用应用程序时,算法的每个用户状态会经历许多小的更改。该算法经常在每个用户的工作中用于做出某些重要的决定。如何让一个web对象中的Python对象持久化?

由于性能原因,对来自(半规范化)数据库数据的每个请求重新初始化状态很快变得不可行。例如,以某种方式缓存状态的Python对象,以便在需要时可以简单地使用和/或更新,这将是非常可取的。但是,由于这是一个Web应用程序,因此有几个进程为请求提供服务,因此使用全局变量是不可能的。我试着序列化相关对象(通过pickle)并将序列化数据保存到数据库,现在我正在试验通过memcached缓存序列化数据。但是,这仍然会经常导致序列化和反序列化的大量开销。

我看过共享内存解决方案,但我发现的唯一相关事项是POSH。然而,POSH似乎没有被广泛使用,我不觉得将这样的实验组件集成到我的应用程序中很容易。

我需要一些建议!这是我开发Web应用程序的第一步,所以我希望这是一个常见的问题,以至于有这样的问题的众所周知的解决方案。在这一点上的解决方案,假设Python的后端是一台服务器上运行就足够了,但加分解决方案,规模到多台服务器以及:)

注:

  • 我有这个应用程序正在工作,目前正在使用并且处于活动状态我开始时没有做任何过早的优化,然后根据需要进行优化。我已经完成了测量和测试,以确保上述问题是实际的瓶颈。我敢肯定,我可以从目前的设置中挤出更多的性能,但我想问问是否有更好的方法。
  • 设置本身仍然是一项工作;假定系统的架构可以是任何套件的解决方案。
+0

哪个框架? CherryPy的? Django的? – 2008-12-01 11:20:26

+0

你有没有做过任何测量证明状态访问是瓶颈?腌菜有多大,取出多少时间,整个请求的时间等等? – 2008-12-01 12:28:35

+0

@Martin:咸菜大约2MB(协议2),反序列化和序列化占用请求处理时间的90%。 – taleinat 2008-12-01 21:51:05

回答

3

我认为multiprocessing框架有什么可能适用于此 - 即共享ctypes模块。

多处理对于Python来说是相当新的,所以它可能有一些奇怪的地方。我不太确定该解决方案是否适用于不通过multiprocessing产生的进程。

2

我想你可以给ZODB一枪。 “

”ZODB的一个主要特性是透明性,不需要编写任何代码来显式读写数据库中的对象,只需将持久对象放入一个像Python字典一样工作的容器中,这个字典中的所有东西都保存在数据库中,这个字典被认为是数据库的“根”,它就像一个魔术包;任何你放进它里面的Python对象都会变成持久的。

Initailly它是Zope的一个组成部分,但最近还有一个独立的软件包。

它具有以下限制:

“。其实有什么你可以在ZODB存储有一些限制,您可以存储可以在任何物体‘腌’到一个标准的,跨平台的串行格式像列表,字典和数字这样的对象可能被腌渍,像文件,套接字和Python代码对象这样的对象不能被存储在数据库中,因为它们不能被腌制。“

我看了,但没有给它一个镜头,自己虽然

其他可能的事情可能是在内存中的SQLite数据库,这可能有点加速过程 - 是一个内存分贝,但你仍然必须做的序列化的东西,所有 注:在内存数据库是对资源的价格

这里是一个链接:。http://www.zope.org/Documentation/Articles/ZODB1

+1

这或多或少是我正在做的 - 用pickle序列化对象并将序列化数据保存到数据库。由于我试图消除序列化和反序列化过程的开销,所以ZODB将无济于事。 – taleinat 2008-12-01 11:38:35

+1

@taleinat,它只在对象退出缓存并且再次请求时才反序列化和序列化。 – Unknown 2009-05-17 02:37:32

8

要谨慎过早优化的

此外:“Python后端运行一种算法,其状态......”是Web框架中的会话。而已。让Django框架在缓存中维护会话状态。期。

“算法的每个用户状态在用户使用该应用程序时会经历许多小的更改。”大多数Web框架都提供了一个缓存会话对象。通常它是非常高的性能。请参阅Django的session documentation

建议。 [修订]

看来你有一些工作。利用学习你的框架,学习工具,并学习你可以转动什么旋钮,而不会冒汗。具体来说,使用会话状态。其次,缓存缓存,会话管理以及易于调整的内容,并查看是否有足够的速度。通过试用MySQL套接字或命名管道是否更快。这些是无编程优化。

第三,测量性能以找到您的实际瓶颈。准备好提供(并捍卫)这些测量的细粒度足够有用和稳定,足以提供备选方案的有意义的比较。

例如,显示持久会话和高速缓存会话之间的性能差异。

1

另一种选择是审查状态的要求,听起来好像序列化是瓶颈然后对象非常大。你真的需要一个大的物体吗?

我知道在Stackoverflow播客27 reddit球员讨论他们用于状态,所以也许有用的倾听。

2

首先您的方法不是一种常见的Web开发实践。即使使用多线程技术,Web应用程序也可以运行多处理环境,以实现可扩展性和更轻松的部署。

如果您只需要初始化一个大对象,并且以后不需要更改,那么可以通过使用在创建WSGI应用程序时初始化的全局变量,或者该模块包含对象被加载等,多处理将为你做的罚款。

如果您需要更改对象并从每个线程访问它,您需要确保您的对象是线程安全的,请使用锁来确保。并使用单个服务器上下文,一个进程。任何多线程python服务器都能很好地为您服务,FCGI也是这种设计的不错选择。但是,如果多个线程正在访问和更改您的对象,那么这些锁可能会对您的性能增益产生非常不利的影响,这可能会使所有好处消失。

2

这是Durus,一个用Python编程语言编写的应用程序的持久对象系统。 Durus提供了一种简单的方法来使用和维护一个或多个进程使用的对象实例的一致集合。通过包含 commit()和abort()方法的缓存的Connection实例来管理持久实例的访问和更改,以便更改是事务性的。

我之前已经用它在一些研究代码,在这里我想坚持某些计算的结果http://www.mems-exchange.org/software/durus/

。我最终转向pytables,因为它更好地满足了我的需求。