Django,sleep()暂停所有进程,只有在没有GET参数时?
我在使用Django(托管在Webfaction上),有以下代码:
import time
def my_function(request):
time.sleep(10)
return HttpResponse("Done")
当我访问我的网址www.mysite.com时,这段代码会被Django执行。
我连续两次输入这个网址。按理说,这两次请求应该都在10秒内完成。然而,第二次请求却要等第一次完成,结果总共花了20秒。
但如果我输入一些虚假的GET参数,比如www.mysite.com?dummy=1和www.mysite.com?dummy=2,那么这两次请求就都能在10秒内完成。所以它们是可以同时运行的。
感觉像是sleep()的作用范围是全局的?也许输入参数让它们作为不同的进程运行,而不是同一个进程??
这个网站是托管在Webfaction上的。httpd.conf文件里有:
KeepAlive Off
Listen 30961
MaxSpareThreads 3
MinSpareThreads 1
ServerLimit 1
SetEnvIf X-Forwarded-SSL on HTTPS=1
ThreadsPerChild 5
我确实需要使用sleep(),并且希望它不会阻止其他请求的执行。那么这是怎么回事,应该怎么解决呢?
补充:Webfaction是通过Apache来运行这个的。
3 个回答
可能只是因为你的浏览器在处理请求时,把第二个请求排队,等第一个请求完成后再执行。如果你是在同一个浏览器中打开网址,可以试试用两个不同的浏览器(比如Firefox和Chrome)。或者,你也可以尝试在命令行中使用 wget
或 curl
来发起请求。
假设你用 run()
命令来启动你的Django服务器,这样默认情况下它会是单线程的服务器。也就是说,服务器一次只能处理一个请求。如果你在这个单线程的进程中使用了睡眠(sleep)功能,那么在睡眠的那段时间里,整个应用都会停下来,无法响应其他请求。
正如Gjordis所说,sleep会让当前的线程暂停。我查看了Webfaction,发现他们是用WSGI来运行Django的服务实例。这意味着,每当有请求进来时,Apache会查看当前有多少个工作进程(每个进程都在运行一个Django实例)。如果没有正在运行的进程,Apache就会启动新的工作进程来处理请求。
在你的情况中,我觉得发生的事情是这样的:
- 首先,资源A的GET请求进来了。Apache使用一个正在运行的工作进程(或者启动一个新的进程)来处理这个请求。
- 这个工作进程暂停了10秒。
- 在这段时间内,又有一个新的资源A的请求进来了。Apache发现这个请求是相同的资源,于是把它发送给了同一个工作进程。这里的假设是,最近处理过这个资源的工作进程可能已经有一些缓存的信息,所以能更快地处理这个请求。
- 结果就是出现了20秒的延迟,因为只有一个工作进程在等待两次10秒。
这种行为在99%的情况下都是合理的,所以默认这样做是有道理的。
但是,如果你在第二个请求中改变了请求的资源(比如添加了GET参数),Apache会认为这是一个不同的资源,并会启动另一个工作进程(因为第一个工作进程已经“忙”了,Apache无法知道你并没有在做什么复杂的工作)。这样就会有两个工作进程,各自等待10秒,总时间就降到了10秒。
另外,我觉得你的设计可能有些**问题**。几乎没有什么情况是合理的,不尽快响应HTTP请求。毕竟,你希望在最短的时间内处理尽可能多的请求,所以暂停10秒是最不划算的做法。我建议你重新提问,说明你实际想要达到的目标。我相信会有更合理的解决方案!