我已经设置了gunicorn与3个工人,30个工人连接和使用eventlet工人类。它被设置在Nginx后面。每请求几次,我就会在日志里看到这个。
[ERROR] gunicorn.error: WORKER TIMEOUT (pid:23475)
None
[INFO] gunicorn.error: Booting worker with pid: 23514
为什么会这样?我怎样才能知道哪里出了问题呢?
我已经设置了gunicorn与3个工人,30个工人连接和使用eventlet工人类。它被设置在Nginx后面。每请求几次,我就会在日志里看到这个。
[ERROR] gunicorn.error: WORKER TIMEOUT (pid:23475)
None
[INFO] gunicorn.error: Booting worker with pid: 23514
为什么会这样?我怎样才能知道哪里出了问题呢?
当前回答
以我为例,我在向服务器发送较大(10MB)文件时遇到了这个问题。我的开发服务器(app.run())收到他们没有问题,但gunicorn无法处理他们。
和我遇到同样问题的人。我的解决方案是像这样把它分成块发送: 参考/ HTML的例子,单独的大文件参考
def upload_to_server():
upload_file_path = location
def read_in_chunks(file_object, chunk_size=524288):
"""Lazy function (generator) to read a file piece by piece.
Default chunk size: 1k."""
while True:
data = file_object.read(chunk_size)
if not data:
break
yield data
with open(upload_file_path, 'rb') as f:
for piece in read_in_chunks(f):
r = requests.post(
url + '/api/set-doc/stream' + '/' + server_file_name,
files={name: piece},
headers={'key': key, 'allow_all': 'true'})
我的烧瓶服务器:
@app.route('/api/set-doc/stream/<name>', methods=['GET', 'POST'])
def api_set_file_streamed(name):
folder = escape(name) # secure_filename(escape(name))
if 'key' in request.headers:
if request.headers['key'] != key:
return 404
else:
return 404
for fn in request.files:
file = request.files[fn]
if fn == '':
print('no file name')
flash('No selected file')
return 'fail'
if file and allowed_file(file.filename):
file_dir_path = os.path.join(app.config['UPLOAD_FOLDER'], folder)
if not os.path.exists(file_dir_path):
os.makedirs(file_dir_path)
file_path = os.path.join(file_dir_path, secure_filename(file.filename))
with open(file_path, 'ab') as f:
f.write(file.read())
return 'sucess'
return 404
其他回答
这招对我很管用:
gunicorn app:app -b :8080 --timeout 120 --workers=3 --threads=3 --worker-connections=1000
如果你有eventlet,添加:
--worker-class=eventlet
如果你有gevent添加:
--worker-class=gevent
我们在使用Django+nginx+gunicorn时也遇到了同样的问题。从Gunicorn文档中,我们配置了优雅的超时,几乎没有什么不同。
经过一些测试,我们找到了解决方案,要配置的参数是:timeout(并且不是优雅超时)。它走得像时钟一样快。
所以,做:
1)打开gunicorn配置文件
2)将TIMEOUT设置为您需要的任何值-以秒为单位
NUM_WORKERS=3
TIMEOUT=120
exec gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--timeout $TIMEOUT \
--log-level=debug \
--bind=127.0.0.1:9000 \
--pid=$PIDFILE
我有非常相似的问题,我也尝试使用“运行服务器”,看看我是否能找到任何东西,但我所拥有的只是一个消息杀死
所以我认为这可能是资源问题,我继续给实例更多的RAM,它工作了。
检查你的工人没有被健康检查杀死。长请求可能会阻塞健康检查请求,worker会被平台杀死,因为平台认为worker没有响应。
例如,如果您有一个25秒长的请求,并且活动检查被配置为每10秒命中同一服务中的不同端点,1秒超时,并重试3次,这就给出了10+1*3 ~ 13秒,您可以看到它会触发一些时间,但并不总是如此。
如果是这种情况,解决方案是重新配置您的活动检查(或您的平台使用的任何健康检查机制),以便它可以等待您的典型请求完成。或者允许更多的线程——这样可以确保健康检查不会阻塞足够长的时间来触发worker kill。
你可以看到,增加更多的工人可能有助于(或隐藏)这个问题。
我在Docker中也遇到了同样的问题。
在Docker中,我保持训练过的LightGBM模型+ Flask服务请求。作为HTTP服务器,我使用gunicorn 19.9.0。当我在我的Mac笔记本电脑上本地运行我的代码时,一切都很完美,但当我在Docker中运行应用程序时,我的POST JSON请求冻结了一段时间,然后gunicorn工人已经失败了[CRITICAL]工人超时异常。
我尝试了大量不同的方法,但唯一解决我的问题的是添加worker_class=gthread。
以下是我的完整配置:
import multiprocessing
workers = multiprocessing.cpu_count() * 2 + 1
accesslog = "-" # STDOUT
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(q)s" "%(D)s"'
bind = "0.0.0.0:5000"
keepalive = 120
timeout = 120
worker_class = "gthread"
threads = 3