使用Gunicorn服务时烧瓶超时

时间:2020-02-03 08:55:52

标签: python flask gunicorn flask-socketio

我有一个将音频文件转换为文本的应用程序。使用烧瓶和烧瓶socketio。当我使用“ python run.py”运行它时,它可以完美运行,但是当我使用“ gunicorn -k eventlet -b 0.0.0.0:5000 run:app”运行它时,它将在调用谷歌的那部分停止在audio.py文件中与文本api对话。

这些是当前的当前代码。

run.py:

from ats import socketio, app, db

if __name__ == '__main__':
    db.create_all()
    socketio.run(app, host='0.0.0.0', port=5001, debug=True)

初始化 .py

import logging, json

from flask import Flask, jsonify, render_template, request
from flask_socketio import SocketIO, emit, send
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmall

app = Flask(__name__, instance_relative_config=True, static_folder="templates/static", template_folder="templates")

# Create db instance
db = SQLAlchemy(app)
ma = Marshmallow(app)

@app.route('/')
def index():
    return render_template('index.html');

# import models
from ats import models

# set up CORS
CORS(app)
socketio = SocketIO(app, cors_allowed_origins='*', async_mode='eventlet')


# import blueprints
from ats.product.product import product_blueprint

# register blueprints
app.register_blueprint(product_blueprint, url_prefix='/api/product')

from ats import error_handlers

product.py

import os
import math
import eventlet
from os.path import join
from flask import Blueprint, request, jsonify, abort
from ats.utils import audio as AUDIO

product_blueprint = Blueprint('product', __name__)

@product_blueprint.route('/add', methods=['post'])
def addProduct():
    try:
        data = request.form

        foldername = data['name']
        scriptFile = request.files['script']
        audioFile = request.files['audio']

        # save the script and audio file to uploads folder
        FILE.createFolder(foldername)
        FILE.save(foldername, scriptFile)
        FILE.save(foldername, audioFile)

        # list the files in the uploads
        audioFiles = FILE.getAudioFileList(foldername)

        fileCount = len(audioFiles)
        currentFile = 1
        # ============ speech to text =============
        for file in audioFiles:
            recognizedText = AUDIO.convert(foldername, file)

            # save to database
            newAudio = {
                'name': file,
                'recognizedText': recognizedText,
                'length': duration,
            }
            Audio.add(newAudio)

            # emit event to update the client about the progress
            percent = math.floor((currentFile / float(fileCount) ) * 100) 
            emit('upload_progress', {'data': percent}, room=data['sid'], namespace='/')
            eventlet.sleep()
            currentFile += 1

        # Delete the files in uploads folder
        FILE.delete(foldername)

        return jsonify({'data': None, 'message': 'Product was added.', 'success': True}), 200
    except Exception as e:
        abort(500, str(e))

audio.py

import os
from ats import app

# Imports the Google Cloud client library
from google.cloud import speech
from google.cloud.speech import enums
from google.cloud.speech import types

# Instantiates a client
client = speech.SpeechClient()

def convert(foldername, filename):
    try:

        file = os.path.join(app.config['UPLOAD_FOLDER'], foldername, filename)

        # Loads the audio into memory
        with io.open(file, 'rb') as audio_file:
            content = audio_file.read()
            audio = types.RecognitionAudio(content=content)

        config = types.RecognitionConfig(
            encoding=enums.RecognitionConfig.AudioEncoding.LINEAR16,
            sample_rate_hertz=48000,
            language_code='ja-JP')

        # Call speech in the audio file
        response = client.recognize(config, audio) # The code will stop here, that results to worker timeout in gunicorn

        return response
    except Exception as e:
        raise e

我一直在寻找解决方案将近一个星期,但仍然找不到。谢谢你是帮助人。

4 个答案:

答案 0 :(得分:2)

当您直接使用python run.py运行应用程序时,不会应用超时,该应用程序需要花费任何处理时间,但是,当您使用Gunicorn运行应用程序时,默认超时为30秒,这意味着您将如果您的应用程序在30秒内没有响应,则会收到超时错误。为避免这种情况,您可以通过添加--timeout <timeinterval-in-seconds>

来增加Gunicorn设置的默认超时时间

以下命令将超时设置为10分钟

gunicorn -k eventlet -b 0.0.0.0:5000 --timeout 600 run:app

答案 1 :(得分:1)

现在可以使用uwsgi而不是gunicorn运行它。这是配置,服务和Nginx

ats.ini

[uwsgi]
module = wsgi:app

master = true
processes = 1

socket = ats.sock
chmod-socket = 660
vacuum = true

die-on-term = true

/etc/systemd/system/ats.service

[Unit]
Description=uWSGI instance to serve ats
After=network.target

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/user/ats
Environment="PATH=/home/user/ats/env/bin"
ExecStart=/home/user/ats/env/bin/uwsgi --ini ats.ini --gevent 100

[Install]
WantedBy=multi-user.target

nginx

server {
    listen 80;
    server_name <ip_address or domain>;
    access_log  /var/log/nginx/access.log;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/user/ats/ats.sock;
        proxy_set_header Connection "Upgrade";

        client_max_body_size 200M;
    }

    location /socket.io {
        include uwsgi_params;
        uwsgi_pass unix:/home/user/ats/ats.sock;
        proxy_set_header Connection "Upgrade";
    }
}

谢谢你们

答案 2 :(得分:0)

Google cloud python与gevent有一些冲突。我从this thread中发现,为了使它们起作用,您需要在init.py的开头添加以下内容:

from gevent import monkey
monkey.patch_all()

import grpc.experimental.gevent as grpc_gevent
grpc_gevent.init_gevent()

答案 3 :(得分:0)

我今天也遇到了这个问题,最后我发现该错误是由代理设置引起的。首先,我将代理设置为“”,

os.environ['http_proxy'] = ""
os.environ['https_proxy'] = ""

在注释代码后,我收到了有关请求超时的错误

# os.environ['http_proxy'] = ""
# os.environ['https_proxy'] = ""

我认为这不是关于gunicore超时默认设置的错误,它是关于系统代理设置的。

相关问题