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?) разрешит вашу проблему.

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

Другие вопросы по тегам