内存Python对象,用于nginx / uwsgi服务器
我怀疑这甚至是可能的,但这里是问题和提出的解决方案(提出的解决方案的可行性是这个问题的目标):
我有一些“全局数据”需要适用于所有请求。 我坚持将这些数据保存到Riak中,并使用Redis作为访问速度的缓存层(现在...)。 数据分成大约30个逻辑块,每个大约8 KB。
每个请求都需要读取这些8KB块中的4块,从Redis或Riak中读取32KB数据。 这对于任何需要读取的请求特定数据都是附加的(这是相当多的)。
假设每秒甚至有3000个请求(这不是一个活动的服务器,所以我没有实际的数字,但3000ps是一个合理的假设,可能会更多),这意味着从Redis或Riak在ADDITION转移96KBps到已经不 - 从应用程序逻辑中创建其他不重要的调用。 此外,Python每秒钟都会解析这些8KB对象的JSON 3000次。
所有这些 - 尤其是Python不得不反复反序列化数据 - 看起来完全是浪费,完美优雅的解决方案是将反序列化的数据缓存在Python中的内存本机对象中,我可以定期刷新当所有这些“静态”数据变得陈旧时。 一分钟(或几小时),而不是每秒3000次。
但我不知道这是否可能。 你实际上需要一个“永远在运行”的应用程序来缓存其内存中的任何数据。 而且我知道nginx + uwsgi + python组合(与类似节点的东西)并不是这种情况 - 除非我非常错误,否则python内存数据不会在所有请求中持续存在,除非我非常错误。
不幸的是,这是一个我已经“继承”的系统,因此无法在基础技术方面做出太多改变,也不足以了解nginx + uwsgi + python组合如何在启动Python过程和持续Python的内存数据 - 这意味着我可能会错过我的假设!
所以,直接建议这个解决方案是否能够工作+引用可以帮助我理解nginx + uwsgi + python如何在启动新进程和内存分配方面起作用的材料,将会大有裨益。
PS:
已经通过了一些关于nginx,uwsgi等的文档,但还没有完全理解我的使用案例的后果。 希望今后能够取得一些进展
如果内存中的东西可以解决,我会查找Redis,因为我只缓存上面提到的静态数据。 这使得进程内持久内存Python缓存对我来说更具吸引力,减少了系统中的一个移动部分,并且每个请求至少执行了四次网络往返。
你所建议的并不是直接可行的。 由于新进程可以在控制之外进行,因此无法将本机Python数据保存在内存中。
但是,有几种解决方法。
通常,您只需要一个级别的键值存储。 有时候,你需要固定大小的缓冲区来存储值(你可以直接使用str
/ bytes
/ bytearray
对象;任何你需要在那里struct
或者序列化的东西)。 在这种情况下,uWSGI的内置缓存框架将负责您所需的一切。
如果你需要更精确的控制,你可以看看如何在SharedArea
之上实现缓存并做一些自定义。 但是,我不会推荐。 它基本上为您提供了与文件相同的API,与使用文件相比,唯一的优点是服务器将管理文件的生命周期; 它适用于所有uWSGI支持的语言,甚至那些不允许文件的语言; 如果您稍后需要,可以更轻松地将自定义缓存迁移到分布式(多计算机)缓存。 我认为这些与你无关。
另一种获得平坦键值存储但没有固定大小缓冲区的方法是使用Python的stdlib anydbm
。 键值查找与python相同:除了它被备份到磁盘上的BDB(或类似的)数据库,在内存中适当地缓存之外,它看起来就像一个dict
,除了存储在内存中之外,内存哈希表。
如果你需要处理其他一些简单的类型 - 任何快速去除/腌制的东西,比如int
s,你可能需要考虑shelve
。
如果您的结构足够僵化,则可以将键值数据库用于顶层,但可以通过ctypes.Structure
访问值,或者使用struct
de / serialize。 但通常情况下,如果你能做到这一点,你也可以消除顶层,此时你的整个事物只是一个大的Structure
或Array
。
在这一点上,你可以使用一个普通的文件来存储 - 或者mmap
(用于ctypes
),或者只是open
并read
它(用于struct
)。
或者使用multiprocessing
的Shared ctypes
对象直接从共享内存区域访问您的Structure
。
与此同时,如果你实际上并不需要所有的缓存数据,那么每隔一段时间就需要一点零碎,这正是数据库的用途。 再次, anydbm
等都可能是你所需要的,但是如果你有复杂的结构,绘制一个ER图,把它变成一组表,并使用类似MySQL的东西。
你没有说过把这些数据写回来,是静态的吗? 在这种情况下,解决方案是每一个简单的,我不知道什么是所有的“这是不可行”的反应。
Uwsgi工人总是运行的应用程序。 所以数据绝对会在请求之间持续存在。 所有你需要做的就是将东西存储在一个全局变量中,就是这样。 并且记住它是每个工作人员,并且工作人员不时会重新启动,因此您需要适当的加载/失效策略。
如果数据很少更新(很少重新启动服务器),则可以节省更多。 在应用程序构建过程中创建对象。 这样,他们将被创建一次,然后所有的工作人员将分离主人,并重复使用相同的数据。 当然,它是在写入时拷贝的,所以如果你更新它,你将失去内存优势(如果python决定在gc运行期间压缩它的内存,同样的事情会发生,所以它不是超级可预测的)。
我从来没有真正尝试过,但是你可以使用uWSGI的SharedArea来完成你的目标吗?
链接地址: http://www.djcxy.com/p/70083.html