[英]How would one make Python objects persistent in a web-app?
我正在编写一个相当复杂的Web应用程序。 Python后端运行一种算法,其状态取决于存储在几个相互关联的数据库表中的数据,这些数据表不经常更改,另外还有经常更改的用户特定数据。 当用户使用应用程序时,算法的每用户状态会经历许多小的更改。 在每个用户的工作中经常使用该算法来做出某些重要决定。
出于性能原因,在(半规范化的)数据库数据的每个请求上重新初始化状态很快就变得不可行。 例如,以某种方式缓存状态的Python对象是非常可取的,这样可以在必要时简单地使用和/或更新它。 但是,由于这是一个Web应用程序,因此有几个进程处理请求,因此使用全局变量是不可能的。
我已经尝试序列化相关对象(通过pickle)并将序列化数据保存到DB,现在我正在尝试通过memcached缓存序列化数据。 但是,这仍然会经常对序列化和反序列化对象产生巨大的开销。
我看过共享内存解决方案,但我发现唯一相关的东西是POSH 。 然而,POSH似乎没有被广泛使用,我觉得将这样的实验组件集成到我的应用程序中并不容易。
我需要一些建议! 这是我开发Web应用程序的第一步,所以我希望这是一个很常见的问题,有这些问题的众所周知的解决方案。 在这一点上,假设Python后端在单个服务器上运行的解决方案就足够了,但对于可扩展到多个服务器的解决方案来说也是额外的点:)
笔记:
过早优化要谨慎。
另外:“Python后端运行一个算法,其状态......”是Web框架中的会话。 而已。 让Django框架在缓存中维护会话状态。 期。
“当用户使用应用程序时,算法的每用户状态会经历许多小的变化。” 大多数Web框架都提供缓存的会话对象。 通常它的性能非常高。 请参阅Django的会话文档 。
咨询。 [修正]
看来你有一些有用的东西。 利用学习你的框架,学习工具,并学习你可以转动的旋钮,而不会流汗。 具体来说,使用会话状态。
其次,摆弄缓存,会话管理和易于调整的事情,看看你是否有足够的速度。 通过试用它们来了解MySQL套接字或命名管道是否更快。 这些是无编程优化。
第三,衡量绩效以找到实际的瓶颈。 准备好提供(并保护)测量结果,使其足够精细,足以提供有意义的替代品比较。
例如,显示持久会话和缓存会话之间的性能差异。
我认为多处理框架在这里可能适用 - 即共享ctypes模块。
多处理对于Python来说是相当新的,因此它可能有些奇怪之处。 我不太确定该解决方案是否适用于未通过multiprocessing
处理生成的流程。
我想你可以给ZODB一个机会。
“ZODB的一个主要特性是透明性。您不需要编写任何代码来显式读取或写入数据库中的对象。您只需将持久对象放入一个像Python字典一样工作的容器中。字典被保存在数据库中。这个字典被称为数据库的“根”。它就像一个魔术包;你放入其中的任何Python对象都变得持久。“
最初它是Zope不可或缺的一部分,但最近也有一个独立的包。
它有以下限制:
“实际上,您可以在ZODB中存储一些限制。您可以将任何可以”腌制“的对象存储为标准的跨平台串行格式。可以对列表,词典和数字等对象进行腌制。像文件,套接字和Python代码对象一样,不能存储在数据库中,因为它们无法被腌制。“
我已经读过了,但是我自己没有给它一个镜头。
其他可能的东西可能是内存中的sqlite数据库,这可能会加快进程 - 作为内存数据库,但你仍然需要做序列化的东西和所有。 注意:在内存中,db的资源很昂贵。
首先,您的方法不是常见的Web开发实践。 即使使用多线程,Web应用程序也可以运行多处理环境,既可扩展又易于部署。
如果您只需要初始化一个大对象,而不需要稍后更改,则可以通过使用在创建WSGI应用程序时初始化的全局变量,或者模块包含正在加载的对象等来轻松地执行此操作,多处理对你来说很好。
如果您需要更改对象并从每个线程访问它,您需要确保您的对象是线程安全的,使用锁来确保。 并使用单个服务器上下文,一个进程。 任何多线程python服务器都能为您提供良好的服务,FCGI也是这种设计的不错选择。
但是,如果多个线程正在访问并更改您的对象,则锁定可能会对您的性能提升产生非常不利的影响,这可能会使所有好处消失。
这是Durus,一种用Python编程语言编写的应用程序的持久对象系统。 Durus提供了一种简单的方法来使用和维护一个或多个进程使用的一致的对象实例集合。 通过包含commit()和abort()方法的缓存Connection实例来管理持久实例的访问和更改,以便更改是事务性的。
http://www.mems-exchange.org/software/durus/
我以前在一些研究代码中使用过它,我希望保留某些计算的结果。 我最终切换到pytables,因为它更好地满足了我的需求。
另一个选择是检查状态的要求,听起来如果序列化是瓶颈,那么对象非常大。 你真的需要一个大的物体吗?
我知道在Stackoverflow播客27中,reddit讨论了他们用于状态的内容,所以听听可能很有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.