Django AJAX запросы во время обычного запроса не проходят
У меня есть сайт Django с веб-страницей для входа. Когда форма входа в систему на странице отправлена, она выполняет представление входа в систему, которое запускает функцию внутри нее, обработка которой занимает много времени (30 секунд или около того). Таким образом, чтобы показать прогресс клиенту во время входа в систему, как только форма будет отправлена, функция JS на странице входа в систему начинает отправлять запросы AJAX POST на сервер (poll_state
view), который возвращает состояние логина. Затем он обновляет HTML-код страницы входа в систему, чтобы показать состояние (например, панель загрузки).
Мой вопрос или проблема в том, что, когда я делаю регулярные python manage.py runserver
с прокси-сервером NGINX это работает безупречно. Но когда я использую Gunicorn вместо python manage.py runserver
запросы AJAX не проходят до тех пор, пока представление входа в систему полностью не обработает и не вернет ответ (который является следующей веб-страницей). Вместо того, чтобы опросить состояние входа в систему, он просто возвращает кучу ошибок для poll_state
просмотр после загрузки следующей веб-страницы.
Когда пользователь отправляет форму входа в систему, сервер выполняет представление входа в систему, и одновременно клиент начинает опросить сервер, используя запросы AJAX. Вот код JS на странице входа в систему, которая отправляет запросы:
let willstop = 0
var poll = function() {
$.ajax({
url:'http://<my server's ip>/poll_state/',
type: 'POST',
data: {
csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),
id: $('#id').val(),
},
success: function(pollResult) {
step = pollResult.data
if (step == 'Done')
willstop = 1
$('#step').html(step)
}
})
}
let refreshIntervalId = setInterval(function() {
poll()
if(willstop == 1) {
clearInterval(refreshIntervalId);
}
}, 500)
Это просто отправляет запрос на мой сервер poll_state
просмотр (я пропустил адрес моего сервера, но могу поделиться им, если это поможет!) каждые полсекунды, пока не завершится вход в систему (step == "Done"), а затем он просто очищает интервал (который является своего рода избыточным, поскольку он перенаправляет на новую страницу в любом случае).
И poll_state
Посмотреть:
def poll_state(request):
""" A view to report the progress to the user """
data = 'Fail'
if request.is_ajax() and request.method == 'POST':
data = loggingInSteps[request.POST.get('id')]
else:
data = 'This is not an ajax request'
result = {'data': data}
return JsonResponse(result)
loggingInSteps
это глобальный диктант на сервере с шагами для всех клиентов. Каждый клиент имеет уникальный идентификатор, который является ключом, а значение - это шаг, на котором находится клиент в процессе входа в систему. Пара ключ-значение удаляется при перенаправлении.
Сервер, на котором я работаю, - это 64-битная капля Ubuntu DigitalOcean, так что это должен быть мой рабочий сервер. Я следовал этому руководству, чтобы настроить сервер, поэтому моя конфигурация NGINX:
server {
listen 80;
server_name cume;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static/ {
alias /home/mikmaks/dev/CUNYsecond/cume/static/;
}
}
И я начинаю Gunicorn либо так gunicorn config.wsgi --bind 127.0.0.1:8000
или как демон: gunicorn config.wsgi --bind 127.0.0.1:8000 --daemon --log-file ~/dev/logs/cume_gunicorn.log --workers=3
Любая версия не работает.
Кто-нибудь знает, может ли Gunicorn принимать запросы AJAX от того же клиента, когда он обрабатывает обычный запрос от него? Возможно, проблема не в Gunicorn, а в моей конфигурации NGINX. Большое спасибо за помощь. Я с удовольствием предоставлю любой код или дополнительную информацию, если это необходимо:)
2 ответа
Используя асинхронный рабочий (в моем случае я использовал gevent
) работал! Теперь Gunicorn обрабатывает несколько запросов одновременно, то есть запрос, который блокировал все (для представления входа в систему), обрабатывается асинхронно, поэтому запросы AJAX проходят.
Я начинаю Gunicorn сейчас с: gunicorn config.wsgi --bind 127.0.0.1:8000 -k gevent --worker-connections 1001 --workers=3
, Единственное, что теперь, когда нагрузка распределяется между 3 работниками, это не так хорошо обновляется, но с 1 работником это работает отлично. Я должен разобраться еще, чтобы посмотреть, смогу ли я заставить его работать с 3 работниками.
Спасибо, Алекс, за помощь!
loggingInSteps is a global dict on the server with the steps for all the clients
может быть проблемой, если у вас есть более одного процесса, обрабатывающего запрос. Словарь может обновляться в одном процессе, но не в другом. Возможно переключение в однопроцессный режим (--workers=1
?) разрешит вашу проблему.
Кроме того, вы можете перепроектировать свое приложение и избавиться от глобальных требований, чтобы оно работало в многопроцессорной среде.