【问题标题】:Python app on heroku platform seems to start on two threadsheroku 平台上的 Python 应用程序似乎在两个线程上启动
【发布时间】:2017-11-01 17:20:06
【问题描述】:

有一个简单的python应用部署在heroku平台上:

from flask import Flask

log("APP STARTED.")
# single time connection to database and logging stuff

app = Flask(__name__)

@app.route('/', methods=['GET'])
# do something

@app.route('/', methods=['POST'])
# do something

过程文件:

web: gunicorn app:app --log-file=-

查看日志时,我发现我上面的代码使用多个线程执行了多次。我知道由于不一致的日志记录,必须涉及更多线程。查看日志:

2017-05-31T17:12:46.415059+00:00 app[web.1]: APP STARTED.   
2017-05-31T17:12:46.415072+00:00 app[web.1]: Executing query.  
2017-05-31T17:12:46.415688+00:00 app[web.1]: APP STARTED.    
2017-05-31T17:12:46.415717+00:00 app[web.1]: Executing query.
2017-05-31T17:12:46.436370+00:00 app[web.1]: Successful connection to database.    
2017-05-31T17:12:46.437398+00:00 app[web.1]: Successful connection to database.    
2017-05-31T17:12:46.439197+00:00 app[web.1]: Success executing query.    
2017-05-31T17:12:46.439680+00:00 app[web.1]: Success executing query.

我也可以在这里看到工作线程:

2017-05-31T18:59:10.046388+00:00 app[web.1]: [2017-05-31 18:59:10 +0000] [9] [INFO] Booting worker with pid: 9    
2017-05-31T18:59:10.132547+00:00 app[web.1]: [2017-05-31 18:59:10 +0000] [11] [INFO] Booting worker with pid: 11

如何防止多个工作线程启动并仅从一个启动?

【问题讨论】:

    标签: python multithreading heroku web-applications


    【解决方案1】:

    您看到的是预期行为。请注意,这些不是线程,而是子进程。默认情况下,gunicorn 是一个分叉服务器——为了处理并发请求,它创建了多个子进程。

    您会看到两个工作进程,因为根据文档 (https://devcenter.heroku.com/articles/python-gunicorn#basic-configuration),gunicorn 遵循 WEB_CONCURRENCY 环境变量,这在 Heroku 上似乎默认为两个。

    您可以通过WEB_CONCURRENCY=2 heroku local 直接在本地复制行为;注意两个工人 pid。然后在没有WEB_CONCURRENCY 变量的情况下运行它,您将只看到一个工作进程 pid。

    如果您真的想将其限制为一个进程,您可以在 .env 文件中或通过 heroku config:set 命令显式设置 WEB_CONCURRENCY 为 1。但是,我建议不要这样做 -

    • 因为它们是进程而不是线程,所以线程同步不是问题。需要注意的是,您不能依赖共享状态(例如,更新模块级变量)。例如,在一个工作人员中实现的hit_counter 变量在第二个工作人员中根本不可见。
    • 并发 dyno 将帮助您更经济有效地扩展。 WEB_CONCURRENCY 大于 1 让您的测功机处理多个并发请求。如果将其限制为 1,则需要多个 dyno 来支持并发请求,并产生相关的 Heroku 费用。

    希望对您有所帮助。

    【讨论】:

    • 好吧。但是如果我将 WEB_CONCURRENCY 设置为 1 并且只运行主进程,我总是可以手动分叉一些进程。并且按照想法,这将与运行 WEB_CONCURENCY 等于 2 的情况相同。我说的对吗?
    • 我不建议这样做 - gunicorn 是专门为您管理并发而构建的。自己动手会带来复杂性 - 何时分叉、何时重新加载、关闭/重新打开哪些资源(如数据库连接)等。您希望通过自己管理流程来实现什么目标?
    • 好吧。我想启动一个主进程来监听传入的消息,并根据它们在队列中添加一个任务供工作人员执行(基本上在主进程中不进行计算)。我所做的是我分叉我的主进程,每 10 分钟有一个第二个,我刷新数据库以查看是否有时间执行命令,如果是,我将该命令添加到另一个工作队列。我相信即使一个分叉的进程会占用一个内核的几乎所有计算能力,它也不会降低主进程的性能,因为它几乎不进行任何计算。
    猜你喜欢
    • 2013-12-20
    • 1970-01-01
    • 1970-01-01
    • 2019-02-22
    • 2021-12-31
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多