简体   繁体   English

在瓶子中的线程之间共享状态

[英]Share state between threads in bottle

In my Bottle app running on pythonanywhere , I want objects to be persisted between requests. 在运行在pythonanywhere上的Bottle应用程序中,我希望对象在请求之间保持不变

If I write something like this: 如果我写这样的话:

X = {'count': 0}

@route('/count')
def count():
    X['count'] += 1
    tpl = SimpleTemplate('Hello {{count}}!')
    return tpl.render(count=X['count'])

The count increments, meaning that X persists between requests. 计数增加,这意味着X在请求之间保持不变。

I am currently running this on pythonanywhere , which is a managed service where I have no control over the web server (nginx I presume?) threading, load balancing (if any) etc... 我目前正在pythonanywhere上运行它,这是一项托管服务,在这里我无法控制Web服务器(我认为是nginx?)线程,负载平衡(如果有)等。

My question is, is this coincidence because it's only using one thread while on minimal load from me doing my tests? 我的问题是,这是巧合吗,因为它仅使用一个线程,而我进行测试的负载却很小?

More generally, at which point will this stop working? 更一般而言,这将在什么时候停止工作? Eg I have more than one thread/socket/instance/load-balanced server etc...? 例如,我有多个线程/套接字/实例/负载均衡服务器等...?

Beyond that, what is my best options to make something like this work (sticking to Bottle) even if I have to move to a barebones server. 除此之外,即使我必须移至准系统服务器,做这样的工作(坚持到瓶子)我最好的选择是什么。

Here's what Bottle docs have to say about their request object: 这是Bottle文档必须针对其请求对象说的话:

A thread-safe instance of LocalRequest. LocalRequest的线程安全实例。 If accessed from within a request callback, this instance always refers to the current request (even on a multi-threaded server). 如果从请求回调中访问,则此实例将始终引用当前请求(即使在多线程服务器上)。

But I don't fully understand what that means, or where global variables like the one I used stand with regards to multi-threading. 但是我不完全理解这意味着什么,或者像我所使用的那样,全局变量在多线程方面的地位如何。

TL;DR: You'll probably want to use an external database to store your state. TL; DR:您可能需要使用外部数据库来存储状态。

If your application is tiny, and you're planning to always have exactly one server process running, then your current approach can work; 如果您的应用程序很小,并且您计划始终只运行一个服务器进程,那么您当前的方法可以工作; "all" you need to do is acquire a lock around every (!) access to the shared state (the dict X in your sample code). 您需要做的“所有”操作是锁定对共享状态的每次访问(!)(示例代码中的dict X )。 (I put "all" in scare quotes there because it's likely to become more complicated than it sounds at first.) (我在这里用“ all”括起来,因为它可能变得比起初听起来更复杂。)

But, since you're asking about multithreading, I'll assume that your application is more than a toy, meaning that you plan to receive substantial traffic and/or want to handle multiple requests concurrently. 但是,由于您正在询问多线程,因此我假设您的应用程序不只是玩具,这意味着您计划接收大量流量和/或希望同时处理多个请求。 In this case, you'll want multiple processes, which means that your approach--storing state in memory--cannot work. 在这种情况下,您将需要多个进程,这意味着您的方法(将状态存储在内存中)无法工作。 Memory is not shared across processes. 内存不跨进程共享。 The (general) way to share state across processes is to store the state externally, eg in a database. 跨进程共享状态的(一般)方法是在外部(例如,在数据库中)存储状态。

Are you familiar with Redis? 您熟悉Redis吗? That'd be on my short list of candidates. 那将在我的候选人短名单上。

I go the answers by contacting PythonAnywhere support, who had this to say: 我通过与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. 当您使用免费的 PythonAnywhere帐户运行网站时,只有一个进程可以处理您的所有请求-因此,像您使用的那样使用全局变量就可以了。 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. 但是,只要您想扩大规模并获得(例如)一个黑客帐户,您就会拥有多个进程(而不是线程)-当然,每个进程都有其自己的全局变量,因此一切都会进行错误。

So that part deals with the PythonAnywhere specifics on why it works, and when it would stop working on there. 因此,该部分讨论了PythonAnywhere的细节,说明了它为什么起作用以及何时停止在那里工作。

The answer to the second part, about how to share variables between multiple Bottle processes, I also got from their support (most helpful!) once they understood that a database would not work well in this situation. 第二部分的答案,关于如何在多个Bottle进程之间共享变量,一旦他们了解到数据库在这种情况下将无法正常运行,我也会得到他们的支持(最有帮助!)。

Different processes cannot of course share variables, and the most viable solution would be to: 当然,不同的流程不能共享变量,最可行的解决方案是:

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?). 编写自己的缓存服务器来处理将内容保存在内存中的过程。您将有一个始终运行的进程,并且Web API请求将以某种方式对其进行访问(内部REST API?)。 It could maintain stuff in memory [...] 它可以将内容保留在内存中[...]

Ps: I didn't expect other replies to tell me to store state in a database, I figured that the fact I'm asking this means I have a good reason not to use a database, apologies for time wasted! 附言:我没想到会有其他回复告诉我将状态存储在数据库中,我发现我要问的事实意味着我有充分的理由不使用数据库,这很浪费时间!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM