我们正在使用以下设置:NGINX + Gunicorn + Flask。我们需要添加一点缓存,每个Flask工作者不超过5Mb。 SimpleCache似乎是最简单的解决方案 - 它在Python进程本身内部使用内存。
不幸的是,文档说明了以下内容:
"单个进程环境的简单内存缓存。这个班 主要存在于开发服务器中,并且不是100%线程安全的。"
但是,在我们的设置中,我没有看到线程安全在哪里都很重要。我认为Gunicorn让几个Flask工作者在运行,每个工人都有自己的小缓存。什么可能出错?
答案 0 :(得分:4)
我目前处理的情况是,在用户登录应用程序后,我想将他的IP,用户名插入数据库。
现在,我只能这样做的方法是使用Cache将用户的ip和用户名存储在缓存中。
现在每个gunicorn进程初始化自己的缓存时都会出现问题。如果为proc1' s缓存添加用户名+ ip组合,如果proc2接收到同一用户的下一个请求,它将无法在其缓存中找到它,因此将其再次添加到其缓存和数据库中,这是不合适。因此,在这种情况下,线程安全(进程安全)缓存很重要。
示例日志:
2015-07-07 22:42:31 - myapp.views:29 - DEBUG - not from cache user1100.100.100.100, <type 'unicode'> [14776]
2015-07-07 22:42:31 - myapp.views:30 - DEBUG - from cache : user1100.100.100.100, <type 'unicode'> [14776]
2015-07-07 22:42:40 - myapp.views:29 - DEBUG - not from cache user1100.100.100.100, <type 'unicode'> [14776]
2015-07-07 22:42:40 - myapp.views:30 - DEBUG - from cache : user1100.100.100.100, <type 'unicode'> [14776]
2015-07-07 22:42:41 - myapp.views:29 - DEBUG - not from cache user1100.100.100.100, <type 'unicode'> [14779]
2015-07-07 22:42:41 - myapp.views:30 - DEBUG - from cache : None, <type 'NoneType'> [14779]
2015-07-07 22:42:41 - myapp.views:32 - DEBUG - new username ip [14779]
2015-07-07 22:42:41 - myapp.views:38 - DEBUG - User : user1, ip : 100.100.100.100, noted at time : Tue Jul 7 22:42:41 2015, login_count : None [14779]
您可以看到gunicorn进程14776首先将其添加到其缓存中,并且下一个请求被14776选中,因此数据库条目只发生一次,但之后,下一个请求被14779选中,并将其添加到其缓存中因此db。
cache = SimpleCache(threshold=1000, default_timeout=3600)
使用基于memcache或redis的缓存可以解决它。我自己正在尝试。
答案 1 :(得分:1)
对于使用gunicorn的用例,没有多线程问题,因为每个服务在其自己的进程中单线程运行。但潜在的问题是“脏”读取数据。
考虑以下情况: