问题描述
我有一个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
视图(我没有服务器的地址,但如果有帮助,可以共享它),每半秒钟一次,直到登录完成(步骤==完成),然后它清除间隔(这是有点多余,因为它重定向至
而 poll_state
查看:
def poll_state(request):
pre>
向用户报告进度的视图
data ='失败'
如果request.is_ajax()和request.method =='POST':
data = loggingInSteps [request.POST.get('id')]
else:
data ='这不是ajax请求'
result = {'data':data}
返回JsonResponse(结果)
loggingInSteps
是服务器上的全局dict,具有所有客户端的步骤。每个客户端都有唯一的ID,这是密钥,值是客户端在登录过程中所执行的步骤。键值对在重定向时被删除。
我正在运行的服务器是64位Ubuntu DigitalOcean液滴,因此它应该是我的生产服务器。我遵循设置服务器,因此我的NGINX配置是:
server {
listen 80;
server_name cume;
位置/ {
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配置。非常感谢您的帮助。我很乐意提供任何代码或附加信息,如有必要:)
解决方案使用异步工作者(在我的情况下,我使用工作的
gevent
)现在,Gunicorn一次处理多个请求,即正在阻止所有内容(到登录视图)的请求正在异步处理,所以AJAX请求通过。
现在启动Gunicorn:
gunicorn config.wsgi --bind 127.0.0.1:8000 -k gevent --worker-connections 1001 --workers = 3
。现在唯一的事情是,当3名工作人员之间分担负载时,它不会更新,但是1名工作人员完全可以正常工作。我将不得不想出更多的东西,看看我能否与3名工作人员合作。
谢谢Alex,帮助!
I have a Django site with a login webpage. When the login form on the page is submitted, it executes the login view, which runs a function inside it that takes a long time to process (30 seconds or so). So in order to show progress to the client during login, as soon as the form is submitted, a JS function on the login page starts making AJAX POST requests to the server (to a
poll_state
view), which returns the state of the login. It then updates the html of the login page to show the state (like a loading bar).My question or problem is that when I do the regular
python manage.py runserver
with an NGINX proxy server it works flawlessly. But when I use Gunicorn instead ofpython manage.py runserver
the AJAX requests don't go through until the login view has completely processed and returned a response (which is the next webpage). Instead of polling the state of the login, it just returns a bunch of errors for thepoll_state
view after the next webpage has loaded.When the user submits the login form, the server executes the login view, and simultaneously the client starts polling the server using AJAX requests. Here is the JS code on the login webpage, which sends the requests:
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)
It's just sends a request to my server's
poll_state
view (I ommitted my server's address, but can share it if it helps!) every half-second until the login is finished (step == "Done"), and then it just clears the interval (which is kinda redundant since it redirects to a new page anyway).And the
poll_state
view: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
is a global dict on the server with the steps for all the clients. Each client has a unique id, which is the key and the value is the step the client is on in the login process. The key-value pair gets deleted upon redirect.The server I am running this on is a 64-bit Ubuntu DigitalOcean droplet, so it's supposed to be my production server. I followed this tutorial to set up the server, so my NGINX configuration is:
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/; } }
And I start Gunicorn either like this
gunicorn config.wsgi --bind 127.0.0.1:8000
or as a daemon like this:gunicorn config.wsgi --bind 127.0.0.1:8000 --daemon --log-file ~/dev/logs/cume_gunicorn.log --workers=3
Either version doesn't work.Does anybody know if Gunicorn can take AJAX requests from the same client as it's processing a normal request from it? Maybe the problem isn't Gunicorn, but is my NGINX configuration. Thank you so much for the help. I'll gladly provide any code or additional info if necessary :)
解决方案Using an asynchronous worker (in my case, I used
gevent
) worked! Now Gunicorn processes multiple requests at a time, i.e. the request that was blocking everything (to the login view) is being processed asynchronously, so the AJAX requests go through.I start Gunicorn up now with:
gunicorn config.wsgi --bind 127.0.0.1:8000 -k gevent --worker-connections 1001 --workers=3
. The only thing is now, when the load is split amongst 3 workers, it doesn't update that well, but with 1 worker it works perfectly. I'll have to figure it out some more to see if I can get it to work with 3 workers.Thank you, Alex, for helping!
这篇关于Django AJAX在定期请求期间不要通过的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!