Как исправить сообщения веб-сокетов, задерживаемые отправкой запроса в настройке Flask-uwsgi-Nginx? - PullRequest
3 голосов
/ 19 июня 2019

Я работаю над приложением Flask с одной веб-страницей, отображаемой с помощью функции render_template Flask.Эта веб-страница содержит форму для отправки данных по запросу + соединение через WebSocket для статуса задачи.При отправке формы запускается запрос на выполнение долгосрочной задачи.Во время выполнения этой длительной задачи имеется несколько сообщений WebSocket, которые отправляются из колбы на эту веб-страницу как статус задачи.Однако даже если эти сообщения отправляются из серверной части в надлежащем порядке, они принимаются на веб-странице только после завершения долгосрочной задачи (иными словами, когда веб-страница получает ответ на запрос формы).Насколько я понимаю, WebSockets являются асинхронными.Так почему же это происходит?

Что я делаю:

Обработчик почтового запроса -> websocket msg 1 -> websocket msg2 -> celery -> ответ на почтовый запрос

Я попытался добавить процессы, потоки и т. Д. В app.ini.

app.ini для uwsgi

[uwsgi]
module = wsgi:app
master = true
http-socket = 127.0.0.1:7001
gevent = 10
http-websockets = true

Конфигурация nginx

server {
    listen 7000;
    server_name _;  

    location / {
        include proxy_params;
    proxy_pass http://127.0.0.1:7001;
    uwsgi_buffering off;
    }

    location /socket.io {
    include proxy_params;
        proxy_http_version 1.1;
    uwsgi_buffering off;
        proxy_buffering off;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_pass http://127.0.0.1:7001/socket.io;

    }
}

web-сокет webpageкод

<script type="text/javascript" charset="utf-8">
        var socket = io.connect('http://' + document.domain + ':' + location.port);

         socket.on('connect', function() {
            socket.emit('get_status')
            socket.emit('get_message')
            console.log('Websocket connected!');
            });

        socket.on('response_status',function(data){
        document.getElementById("status").innerHTML = "Status : "+data.status;
        console.log("status received");
    });


        socket.on('response_last_message',function(data){
        document.getElementById("message").innerHTML = "Message : "+data.last_message;
        console.log("Message received");
    });


</script>

код Python:

основной класс

socketio = SocketIO()

def create_app():
    app = Flask(__name__)
    api = Api(app)
    socketio.init_app(app)


    with open('config.json', 'r') as conf:
        configObject = json.load(conf)

    commonConfig = commons.Common(configObject)
    socketWork = commons.SocketWork(socketio, commonConfig)


    api.add_resource(routes.IndexPage,'/', resource_class_kwargs={ 'commonConfig': commonConfig, 'socketWork': socketWork})
    api.add_resource(routes.UploadFile, '/uploadFile', resource_class_kwargs={ 'commonConfig': commonConfig, 'socketWork': socketWork})


    return app

класс сокетов

class SocketWork():

    def __init__(self, socketio = None, commonObj=None):
        self.commonObj = commonObj
        self.socketio = socketio
        self.socketio.on_event('get_status',self.send_last_status)
        self.socketio.on_event('get_message',self.send_last_message)

    def send_last_status(self):
        print("Send status now")
        status = self.commonObj.status
        self.socketio.emit("response_status", {"status": status})

    def send_last_message(self):
        print("Send last message")
        msg = self.commonObj.msg
        self.socketio.emit("response_last_message", {"last_message": msg})

    def send_message(self,msg):
        self.commonObj.msg = msg
        self.send_last_message()

    def send_status(self,statusVal):
        self.commonObj.status = statusVal
        self.send_last_status()

метод продолжительной работы:

class UploadFile(Resource):

    def __init__(self, **kwargs):
        self.commonConfig = kwargs['commonConfig']
        self.socketWork    = kwargs['socketWork']

    @use_args(args.argsUploadData)
    def post(self, args):
        msg = "This is socket message"
        socketWork.send_message(msg)
        socketWork.send_status(commonConfig.config['Status']['READY'])
        sleep(15)       ###long running task
        return constants.generic_msg.PROCESSING_QUERY.name

Ожидается, что WebSockets на веб-странице получит сообщения от бэкэнда колбы мгновенно, но получит сообщения после завершения почтового запроса.Сообщение об ошибке не генерируется.

1 Ответ

0 голосов
/ 25 июня 2019

После прочтения многих статей я узнал, что ошибка произошла из-за того, что НЕ обезьяна исправила мою программу.Я должен был лучше взглянуть на документацию самого Gevent.Эта ссылка поможет кому-то, если у него возникла та же проблема: GeventDoc .

Кроме того, помните, что исправление обезьян должно быть первым в вашем коде. До любого другого импорта.

...