Тайм-аут фляги при подаче с использованием пушки

У меня есть приложение, которое преобразует аудиофайл в текст. Используя колбу и колбу-сокетио. Он отлично работает, когда я запускаю его с помощью: "python run.py", но когда я запускаю его с помощью: "gunicorn -k eventlet -b 0.0.0.0:5000 run: app", он останавливается на той части, где он вызывает Google речь в текст api в файле audio.py.

Это текущие коды прямо сейчас.

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)

init .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

Я искал решение почти неделю, но так и не нашел. Спасибо за помощь, ребята.


person Hokage Sama    schedule 03.02.2020    source источник
comment
Вы, как обезьяна, исправляете стандартную библиотеку, чтобы она была совместима с eventlet?   -  person Miguel    schedule 04.02.2020
comment
Да, я добавил исправление обезьяны в свой файл init вверху, но все равно это не работает. Я просто использую uwsgi с gevent вместо gunicorn для его запуска и создал службу в systemd на сервере ubuntu. И теперь это работает. Спасибо   -  person Hokage Sama    schedule 05.02.2020


Ответы (4)


Когда вы запускаете приложение напрямую с помощью python run.py, таймаут не применяется, приложение занимает столько времени, сколько ему нужно для обработки, однако, когда вы запускаете приложение с помощью Gunicorn, тайм-аут по умолчанию составляет 30 секунд, что означает, что вы получите ошибку тайм-аута, если ваше приложение не отвечает в течение 30 секунд. Чтобы избежать этого, вы можете увеличить тайм-аут по умолчанию, установленный Gunicorn, добавив --timeout <timeinterval-in-seconds>

Следующая команда устанавливает тайм-аут 10 минут.

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

person Community    schedule 03.02.2020
comment
Спасибо за ваш отзыв, сэр, я попробую это и сообщу вам позже, если это сработает. - person Hokage Sama; 03.02.2020
comment
Вот обновление, сэр, я пробовал его с --timeout 600, но он просто подождет 600 секунд, прежде чем появится тайм-аут. Преобразование аудио в текст обычно занимает от 1 до 2 секунд. Думаю, здесь есть еще одна проблема. - person Hokage Sama; 03.02.2020
comment
Задание тайм-аута в 600 секунд не заставляет сервер ждать 600 секунд, чтобы ответить, скорее он ждет максимум 600 секунд, а затем дает тайм-аут, если сервер по-прежнему не отвечает. Тайм-аут возникает только тогда, когда ваш сервер не отвечает клиенту в течение указанного времени. - person ; 03.02.2020
comment
Есть еще одна проблема с преобразованием речи Google в текст с помощью Gunicorn. Когда я запускаю только флягу, запрос выполняется в течение 2 минут. Каким-то образом преобразование речи Google в текст с помощью Gunicorn заставляет программу зависать ... - person Pinyi Wang; 08.07.2020

Теперь он работает, запустив его с использованием 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";
    }
}

Спасибо вам, ребята

person Hokage Sama    schedule 05.02.2020
comment
Вы когда-нибудь придумали, как заставить его работать с Gunicorn? Я не слишком хорошо знаком с Nginx и uwsgi. - person James B; 29.03.2020
comment
Я смог заставить его работать, используя uwsgi вместо gunicorn sir. - person Hokage Sama; 01.04.2020

Облачный питон Google имел некоторый конфликт с gevent. Я узнал из этой ветки, что для их работы необходимо добавить следующее в начале init.py:

from gevent import monkey
monkey.patch_all()

import grpc.experimental.gevent as grpc_gevent
grpc_gevent.init_gevent()
person Pinyi Wang    schedule 08.07.2020

Я тоже столкнулся с этой проблемой сегодня, наконец, я обнаружил, что ошибка вызвана настройкой прокси. сначала я установил свой прокси,

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

и я получаю сообщение об ошибке тайм-аута в запросе после того, как я прокомментирую код, и он работает

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

Я думаю, что это ошибка не в настройке тайм-аута по умолчанию, а в настройке системного прокси.

person zhicheng duan    schedule 20.07.2020