Django 1.4.18 dev server slow to respond under Vir

2019-04-12 16:21发布

问题:

We're running our development environment in a virtualbox Ubuntu LTS 12.04 guest, in Windows 7 host. We use ./manage.py runserver during development.

Recently we upgraded our Django version to latest (1.4.19) but noticed a very odd behaviour: requests coming from host machine take anything from 5-30s to serve, while requests from inside VM are served in less than a second, as they should be. The problem has been introduced in Django 1.4.18 (https://docs.djangoproject.com/fr/1.7/releases/1.4.18/), all older releases work fast.

Using different browser in guest or host makes no difference. It also does not make any difference whether the requested resource is dynamic or static (we use the static app to serve static content during development).

What could cause this kind of behaviour? From the release notes it's not immediately clear to us.

回答1:

Wow I can't believe I finally managed to solve this. I had exactly the same issue and you put me on the right track by mentioning that it only appeared for version later than Django 1.4.17.

Short solution: add your gateway IPs to /etc/hosts in your guest machine, e.g:

10.0.2.2 10.0.2.2

Long explanation: Django 1.4.18 introduced the stripping of headers that contain underscores. That's harmless, but the django.core.servers.basehttp.WSGIRequestHandler.get_environ method was slightly altered. From 1.4.18 on, it relies on wsgiref.simple_server.WSGIRequestHandler.get_environ, which contains the line:

host = self.address_string()

address_string is a method from BaseHTTPServer:

 def address_string(self):
    """Return the client address formatted for logging.

    This version looks up the full hostname using gethostbyaddr(),
    and tries to find a name that contains at least one dot.

    """

    host, port = self.client_address[:2]
    return socket.getfqdn(host)

That call to getfqdn is the (slow) culprit:

In [1]: import socket
In [2]: %time socket.getfqdn("10.0.2.2")
CPU times: user 0 ns, sys: 0 ns, total: 0 ns
Wall time: 1.56 s
Out[2]: '10.0.2.2'

After I added the "10.0.2.2 10.0.2.2" line to /etc/hosts in my guest machine, hostname resolution was near instant:

In [3]: %time socket.getfqdn("10.0.2.2")
CPU times: user 0 ns, sys: 0 ns, total: 0 ns
Wall time: 834 µs
Out[3]: '10.0.2.2'

Note that your gateway address can be found by running route -n in your guest environment.