我有一个login网页的Django网站。 当页面上的login表单被提交时,它会执行login视图,里面运行一个需要很长时间处理的函数(30秒左右)。 所以为了在login过程中向客户端显示进度,一旦表单被提交,login页面的一个JS函数开始向服务器发出AJAX POST请求(到一个poll_state
视图),它返回login状态。 然后更新login页面的html来显示状态(如加载栏)。
我的问题是,当我用NGINX代理服务器执行普通的python manage.py runserver
,它的工作是完美的。 但是,当我使用Gunicorn而不是python manage.py runserver
,AJAX请求不会经过,直到login视图完全处理并返回响应(这是下一个网页)。 它不是轮询login状态,而是在下一个网页加载完成后,为poll_state
视图返回一堆错误。
当用户提交login表单时,服务器执行login视图,同时客户机开始使用AJAX请求轮询服务器。 这是login网页上的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
视图(我省略了我的服务器的地址,但可以共享,如果有帮助!)每半秒钟,直到login完成(步骤==“完成”),然后它只是清除间隔(这是有点多余,因为它redirect到一个新的一页无论如何)。
和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,这是关键,价值是客户端在login过程中的步骤。 键值对在redirect时被删除。
我运行的服务器是64位的Ubuntu DigitalOcean液滴,所以它应该是我的生产服务器。 我按照这个教程来设置服务器,所以我的NGINXconfiguration是:
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 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,而是我的NGINXconfiguration。 十分感谢你的帮助。 如果需要,我会很乐意提供任何代码或附加信息:)
使用异步工作(在我的情况下,我使用gevent
)工作! 现在,Gunicorn一次处理多个请求,即异步处理阻塞所有内容(到登录视图)的请求,以便AJAX请求通过。
我现在开始gunicorn config.wsgi --bind 127.0.0.1:8000 -k gevent --worker-connections 1001 --workers=3
: gunicorn config.wsgi --bind 127.0.0.1:8000 -k gevent --worker-connections 1001 --workers=3
。 现在唯一的情况是,当负载分配给3名工作人员时,并不能很好地更新,但只有1名工作人员可以很好地工作。 我将不得不弄清楚一些,看看能否和3名工人一起工作。
谢谢Alex,帮忙!
loggingInSteps is a global dict on the server with the steps for all the clients
如果您有多个处理请求的进程loggingInSteps is a global dict on the server with the steps for all the clients
可能都是问题。 字典可以在一个进程中更新,但不能在另一个进程中更新。 也许切换到单进程模式( --workers=1
?)将解决您的问题。
或者,你可以重新设计你的应用程序,并摆脱全球字典,使其在多进程环境中工作