heroku平台上的Python应用程序似乎从两个线程开始

时间:2017-05-31 18:53:01

标签: python multithreading heroku web-applications

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

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

Procfile:

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

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

1 个答案:

答案 0 :(得分:3)

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

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

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

如果您确实希望将其限制为一个进程,则可以在.env文件中或通过WEB_CONCURRENCY命令将heroku config:set显式设置为1。但是,我建议反对 -

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

希望有所帮助。