在瓶中的线程之间共享状态
Share state between threads in bottle
在我的 Bottle app running on pythonanywhere 中,我希望在请求之间保留对象。
如果我这样写:
X = {'count': 0}
@route('/count')
def count():
X['count'] += 1
tpl = SimpleTemplate('Hello {{count}}!')
return tpl.render(count=X['count'])
计数递增,这意味着 X 在请求之间持续存在。
我目前 运行 在 pythonanywhere 上使用它,这是一项托管服务,我无法控制 Web 服务器(我想是 nginx?)线程、负载平衡(如果有)等...
我的问题是,这是巧合吗,因为它只使用一个线程,而我在做测试时负载最小?
更一般地说,这将在什么时候停止工作?例如。我有不止一台 thread/socket/instance/load-balanced 服务器等等...?
除此之外,即使我必须转移到准系统服务器,我做这样的事情的最佳选择是什么(坚持使用 Bottle)。
以下是 Bottle docs 对他们的 请求 对象的看法:
A thread-safe instance of LocalRequest. If accessed from within a request callback, this instance always refers to the current request (even on a multi-threaded server).
但我不完全理解这意味着什么,或者我使用的全局变量在多线程方面的立场。
TL;DR:您可能希望使用外部数据库来存储您的状态。
如果您的应用程序很小,并且您打算始终只拥有一个服务器进程 运行,那么您当前的方法可以奏效; "all" 您需要做的是在每次(!)访问共享状态(示例代码中的字典 X
)时获取一个锁。 (我把 "all" 放在引号里,因为它可能比一开始听起来更复杂。)
但是,由于您询问的是多线程,我假设您的应用程序不仅仅是一个玩具,这意味着您计划接收大量流量 and/or 希望同时处理多个请求。在这种情况下,您将需要多个进程,这意味着您的方法——将状态存储在内存中——行不通。内存不跨进程共享。跨进程共享状态的(一般)方式是在外部存储状态,例如在数据库中。
你熟悉Redis吗?那会在我的候选名单上。
我通过联系 PythonAnywhere 支持找到答案,他们是这样说的:
When you run a website on a free PythonAnywhere account, just
one process handles all of your requests -- so a global variable like
the one you use there will be fine. But as soon as you want to scale
up, and get (say) a hacker account, then you'll have multiple processes
(not, not threads) -- and of course each one will have its own global
variables, so things will go wrong.
因此,该部分涉及 PythonAnywhere 的具体细节,说明它为何工作,以及何时停止工作。
第二部分的答案,关于如何在多个 Bottle 进程之间共享变量,我也得到了他们的支持(最有帮助!)一旦他们明白数据库在这种情况下无法正常工作。
不同的进程当然不能共享变量,最可行的解决方案是:
write your own kind of caching server to handle keeping stuff in memory [...] You'd have one process that ran all of the time, and web API requests would access it somehow (an internal REST API?). It could maintain stuff in memory [...]
Ps: 没想到其他回复告诉我把状态存到数据库里,我想我这么问说明我有充分的理由不使用数据库,抱歉浪费了时间!
在我的 Bottle app running on pythonanywhere 中,我希望在请求之间保留对象。
如果我这样写:
X = {'count': 0}
@route('/count')
def count():
X['count'] += 1
tpl = SimpleTemplate('Hello {{count}}!')
return tpl.render(count=X['count'])
计数递增,这意味着 X 在请求之间持续存在。
我目前 运行 在 pythonanywhere 上使用它,这是一项托管服务,我无法控制 Web 服务器(我想是 nginx?)线程、负载平衡(如果有)等...
我的问题是,这是巧合吗,因为它只使用一个线程,而我在做测试时负载最小?
更一般地说,这将在什么时候停止工作?例如。我有不止一台 thread/socket/instance/load-balanced 服务器等等...?
除此之外,即使我必须转移到准系统服务器,我做这样的事情的最佳选择是什么(坚持使用 Bottle)。
以下是 Bottle docs 对他们的 请求 对象的看法:
A thread-safe instance of LocalRequest. If accessed from within a request callback, this instance always refers to the current request (even on a multi-threaded server).
但我不完全理解这意味着什么,或者我使用的全局变量在多线程方面的立场。
TL;DR:您可能希望使用外部数据库来存储您的状态。
如果您的应用程序很小,并且您打算始终只拥有一个服务器进程 运行,那么您当前的方法可以奏效; "all" 您需要做的是在每次(!)访问共享状态(示例代码中的字典 X
)时获取一个锁。 (我把 "all" 放在引号里,因为它可能比一开始听起来更复杂。)
但是,由于您询问的是多线程,我假设您的应用程序不仅仅是一个玩具,这意味着您计划接收大量流量 and/or 希望同时处理多个请求。在这种情况下,您将需要多个进程,这意味着您的方法——将状态存储在内存中——行不通。内存不跨进程共享。跨进程共享状态的(一般)方式是在外部存储状态,例如在数据库中。
你熟悉Redis吗?那会在我的候选名单上。
我通过联系 PythonAnywhere 支持找到答案,他们是这样说的:
When you run a website on a free PythonAnywhere account, just one process handles all of your requests -- so a global variable like the one you use there will be fine. But as soon as you want to scale up, and get (say) a hacker account, then you'll have multiple processes (not, not threads) -- and of course each one will have its own global variables, so things will go wrong.
因此,该部分涉及 PythonAnywhere 的具体细节,说明它为何工作,以及何时停止工作。
第二部分的答案,关于如何在多个 Bottle 进程之间共享变量,我也得到了他们的支持(最有帮助!)一旦他们明白数据库在这种情况下无法正常工作。
不同的进程当然不能共享变量,最可行的解决方案是:
write your own kind of caching server to handle keeping stuff in memory [...] You'd have one process that ran all of the time, and web API requests would access it somehow (an internal REST API?). It could maintain stuff in memory [...]
Ps: 没想到其他回复告诉我把状态存到数据库里,我想我这么问说明我有充分的理由不使用数据库,抱歉浪费了时间!