Передача flask .request в другой поток - PullRequest
0 голосов
/ 29 марта 2020

Я немного озадачен тем, могу ли я или не могу отправить объект Flask request в другой поток для обработки. Я пытаюсь сохранить данные, связанные с запросом, в Elasticsearch, используя after_request. Чтобы обработать запрос как можно быстрее, я пытаюсь перенести обработку в отдельный поток:

from datetime import datetime
import socket
from threading import Thread

from elasticsearch import Elasticsearch
from flask import current_app, request

def after_request(response):
    Thread(
        target=_process_data, args=(
            current_app._get_current_object(),
            request._get_current_object()
        )
    ).start()

    return response

def _process_data(app, request):
    data = {
        'timestamp': datetime.utcnow(),
        'scheme': request.environ.get('REQUEST_SCHEME'),
        'protocol': request.environ.get('SERVER_PROTOCOL'),
        'method': request.environ.get('REQUEST_METHOD'),
        'uri': request.environ.get('REQUEST_URI'),
        'remote_addr': request.environ.get('REMOTE_ADDR'),
        'remote_port': int(request.environ.get('REMOTE_PORT')),
        'server_name': request.environ.get('SERVER_NAME'),
        'server_port': int(request.environ.get('SERVER_PORT')),
        'app_server': socket.gethostname(),
        'request_headers': dict(request.headers)
    }

    elastic = Elasticsearch('localhost:9200')
    elastic.index(index=app.config['TRACKING_ES_INDEX'], doc_type='_doc', body=data)

Однако в Elasticsearch я начал видеть документы с пустым полем request_headers ({}), особенно при нагрузочном тестировании приложения. Когда я попытался переместить заполнение словаря data в after_request и передать вместо него data в _process_data, все работает как ожидалось.

Документация сообщает:

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

Однако пара абзацев позже , в нем говорится:

Ссылка на объект прокси необходима в некоторых ситуациях, таких как отправка сигналов или передача данных в фоновый поток.

Итак, я Предполагается, что использование request._get_current_object() для получения реального объекта и передачи его в разделенный поток будет работать. Но, видимо, я кое-что упускаю ...

...