问题
We've lately been experiencing a very strange but very consistent delay when POSTing from client-side javascript to our server.
Here's our technology stack, from front to back:
- Custom javascript client code
- Backbone.js
- Custom Backbone.sync() implementation
- jQuery.ajax() (1.7.2)
- XmlHttpRequest
- Browser (verified on both Firefox and Chrome)
- Internet
- Nginx front-end
- Intranet (via Nginx
http://
upstream) - Nginx back-end
- Gunicorn (via Nginx
unix://
upstream socket) - Django 1.4
- django-tastypie
(Side note: do you ever just step back in awe at how complicated web development is?)
Here's a timeline of events:
- Client code calls
.save()
on a newly created Backbone APIModel. - Our custom .sync() winds its way to client.send() which dispatches the newly created object to $.ajax().
- The resulting XmlHttpRequest POSTs. The request appears in the browser dev tool's Network pane, marked as pending.
- The HTTP request reaches Nginx, which routes it to the django-tastypie backend.
- Tastypie handles the request promptly and flawlessly, creating the resource, and returning a 201 CREATED response, with a
Location
header pointing to the new resource. - Nginx logs the request and (ostensibly) sends the response.
- 1.1 minutes elapse, during which the request is still marked as pending in the Network pane.
- The request is marked as complete in the browser's Network pane.
- The jQuery
xhr
fires success handlers - Our custom API client's success handler detects the 201 response code and fires off a subsequent GET request to the Location.
- The usual stuff happens, the GET responds promptly, and the outermost
$.Deferred()
object resolves, firing any associated client code success handlers.
Other details to consider:
- GET requests and PUT requests in the same stack resolve promptly.
- When interacting directly with the outermost Nginx via a dedicated HTTP client, POST requests identical to the request in question resolve promptly.
- Removing the special-case 201 handler and subsequent GET has no effect on the bug.
- The delay is always 1.1 minutes. I've used
console.time()
to determine that the delay varies within the 65,000ms range. - The delay only appears in this configuration. It does not occur in our development setups, which are slightly simpler.
Unverified assumptions I'm making:
- Once Nginx logs a request, the response has been tied up with a bow and sent to the client with a handwritten thank-you note.
- This is not a bug in the browsers or in jQuery.
Forgive the painstaking detail, but I've done my best to eliminate variables, and at present, I feel safe in saying that the problem is one of the following:
- a flaw in the physical structure of the universe
- a flaw in the perceptual models of our minds
- something else we haven't considered yet
I'm hoping for #3. Any ideas?
回答1:
Mystery solved! It was the Content-Length
header, or rather, the lack of one. @MaxDounin had the right idea, I just didn't follow it far enough.
Enabling Django's django.middleware.http.ConditionalGetMiddleware
did the trick. (This middleware sets the Content-Length
header.)
来源:https://stackoverflow.com/questions/12606898/mysterious-1min-delay-in-http-post-between-browser-and-nginx