Я немного озадачен тем, могу ли я или не могу отправить объект 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()
для получения реального объекта и передачи его в разделенный поток будет работать. Но, видимо, я кое-что упускаю ...