Django AJAX在常规请求期间请求不通过

时间:2017-01-03 02:09:29

标签: ajax django nginx gunicorn

我有一个带登录网页的Django网站。当提交页面上的登录表单时,它会执行登录视图,该视图在其中运行一个需要很长时间才能处理的函数(大约30秒左右)。因此,为了在登录期间向客户端显示进度,一旦提交表单,登录页面上的JS函数就开始向服务器发送AJAX POST请求(到poll_state视图),这将返回状态登录。然后它会更新登录页面的html以显示状态(如加载栏)。

我的问题或问题是,当我使用NGINX代理服务器执行常规python manage.py runserver时,它可以正常运行。但是当我使用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视图发送请求(我省略了我的服务器的地址,但是如果它有帮助可以分享它!)每半秒一次,直到登录完成(步骤==“完成”) ,然后它只是清除间隔(这有点多余,因为它无论如何重定向到新页面。)

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是服务器上的全局字典,包含所有客户端的步骤。每个客户端都有一个唯一的id,这是密钥,值是客户端在登录过程中所处的步骤。重定向时删除键值对。

我运行它的服务器是一个64位的Ubuntu DigitalOcean droplet,所以它应该是我的生产服务器。我跟着this tutorial设置了服务器,所以我的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 config.wsgi --bind 127.0.0.1:8000或像这样的守护进程开始Gunicorn:gunicorn config.wsgi --bind 127.0.0.1:8000 --daemon --log-file ~/dev/logs/cume_gunicorn.log --workers=3 这两个版本都不起作用。

有人知道Gunicorn是否可以从同一个客户端接收AJAX请求,因为它正在处理来自它的正常请求?也许问题不是Gunicorn,而是我的NGINX配置。非常感谢你的帮助。如有必要,我很乐意提供任何代码或其他信息:)

2 个答案:

答案 0 :(得分:3)

使用异步工作者(在我的情况下,我用gevent)工作了!现在,Gunicorn一次处理多个请求,即正在异步处理阻塞所有请求(到登录视图)的请求,因此AJAX请求将通过。

我现在用gunicorn config.wsgi --bind 127.0.0.1:8000 -k gevent --worker-connections 1001 --workers=3启动Gunicorn。现在唯一的事情就是,当负载在3个工人之间分配时,它不能很好地更新,但是对于1个工人来说它完美地工作。我将不得不弄清楚它是否可以让它与3名工人一起工作。

谢谢Alex,求助!

答案 1 :(得分:2)

如果您有多个进程处理请求,则

loggingInSteps is a global dict on the server with the steps for all the clients可能会出现问题。字典可以在一个进程中更新,但不能在另一个进程中更新。也许切换到单进程模式(--workers=1?)将解决您的问题。

或者,您可以重新设计应用程序并摆脱全局字典以使其在多进程环境中工作