Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django, sleep() pauses all processes, but only if no GET parameter?

Using Django (hosted by Webfaction), I have the following code

import time
def my_function(request):
    time.sleep(10)
    return HttpResponse("Done")

This is executed via Django when I go to my url, www.mysite.com

I enter the url twice, immediately after each other. The way I see it, both of these should finish after 10 seconds. However, the second call waits for the first one and finishes after 20 seconds.

If, however, I enter some dummy GET parameter, www.mysite.com?dummy=1 and www.mysite.com?dummy=2 then they both finish after 10 seconds. So it is possible for both of them to run simultaneously.

It's as though the scope of sleep() is somehow global?? Maybe entering a parameter makes them run as different processes instead of the same???

It is hosted by Webfaction. httpd.conf has:

KeepAlive Off
Listen 30961
MaxSpareThreads 3
MinSpareThreads 1
ServerLimit 1
SetEnvIf X-Forwarded-SSL on HTTPS=1
ThreadsPerChild 5

I do need to be able to use sleep() and trust that it isn't stopping everything. So, what's up and how to fix it?

Edit: Webfaction runs this using Apache.

like image 528
user984003 Avatar asked Feb 26 '13 08:02

user984003


People also ask

Is time sleep blocking?

The reason you'd want to use wait() here is because wait() is non-blocking, whereas time. sleep() is blocking. What this means is that when you use time. sleep() , you'll block the main thread from continuing to run while it waits for the sleep() call to end.

How to use the sleep command in Python?

If you've got a Python program and you want to make it wait, you can use a simple function like this one: time. sleep(x) where x is the number of seconds that you want your program to wait.

How to put a pause in a Python script?

Python sleep() function will pause Python code or delay the execution of program for the number of seconds given as input to sleep(). The sleep() function is part of the Python time module. You can make use of Python sleep function when you want to temporarily halt the execution of your code.


2 Answers

Assuming you run your Django-server just with run() , by default this makes a single threaded server. If you use sleep on a single threaded process, the whole application freezes for that sleep time.

like image 30
Gjordis Avatar answered Sep 19 '22 05:09

Gjordis


As Gjordis pointed out, sleep will pause the current thread. I have looked at Webfaction and it looks like their are using WSGI for running the serving instance of Django. This means, every time a request comes in, Apache will look at how many worker processes (that are processes that each run a instance of Django) are currently running. If there are none/to view it will spawn additonally workers and hand the requests to them.

Here is what I think is happening in you situation:

  • first GET request for resource A comes in. Apache uses a running worker (or starts a new one)
  • the worker sleeps 10 seconds
  • during this, a new request for resource A comes in. Apache sees it is requesting the same resource and sends it to the same worker as for request A. I guess the assumption here is that a worker that recently processes a request for a specific resource it is more likely that the worker has some information cached/preprocessed/whatever so it can handle this request faster
  • this results in a 20 second block since there is only on worker that waits 2 times 10 seconds

This behavior makes completely sense 99% of the time so it's logically to do this on default.

However, if you change the requested resource for the second request (by adding GET parameter) Apache will assume that this is a different resource and will start another worker (since the first one is already "busy" (Apache can not know that you are not doing any hard work). Since there are now two worker, both waiting 10 seconds the total time goes down to 10 seconds.


Additionally I assume that something is wrong with your design. There are almost no cases which I can think of where it would be sensible to not respond to a HTTP request as fast as you can. After all, you want to serve as many requests as possible in the shortest amount of time, so sleeping 10 seconds is the most counterproductive thing you can do. I would recommend the you create a new question and state what you actual goal is that you are trying to achieve. I'm pretty sure there is a more sensible solution to this!
like image 168
Martin Thurau Avatar answered Sep 21 '22 05:09

Martin Thurau