我们最近在从客户端javascript发布到服务器时遇到了一个非常奇怪但非常一致的延迟。
这是我们的技术堆栈,从前到后:
- 自定义javascript客户端代码
- Backbone.js
- 自定义Backbone.sync()实现
- jQuery.ajax()(1.7.2)
- XmlHttpRequest
- 浏览器(已在Firefox和Chrome上验证)
- 互联网
- Nginx前端
- 内联网(通过Nginx
http://
上游) - Nginx后端
- Gunicorn(通过Nginx
unix://
上游插座) - Django 1.4
- django tastypie
(旁注:你有没有对复杂的web开发感到敬畏?)
以下是事件的时间表:
- 客户端代码在新创建的主干
APIModel
上调用.save()
- 我们的自定义
.sync()
迂回到client.send()
,后者将新创建的对象分派到$.ajax()
- 生成的XmlHttpRequest POST。该请求显示在浏览器开发工具的"网络"窗格中,标记为挂起
- HTTP请求到达Nginx,后者将其路由到django-tastypie后端
- Tastypie迅速而完美地处理请求,创建资源,并返回201 CREATED响应,其中
Location
标头指向新资源 - Nginx记录请求并(表面上)发送响应
- 1.1分钟后,在此期间,请求仍在"网络"窗格中标记为挂起
- 该请求在浏览器的"网络"窗格中标记为完成
- jQuery
xhr
触发成功处理程序 - 我们定制的API客户端的成功处理程序检测到201响应代码,并向Location发出后续的GET请求
- 通常情况下,GET会迅速响应,最外层的
$.Deferred()
对象会解析,从而触发任何相关的客户端代码成功处理程序
其他需要考虑的细节:
- 同一堆栈中的GET请求和PUT请求会迅速解析
- 当通过专用的HTTP客户端直接与最外层的Nginx交互时,与所讨论的请求相同的POST请求会迅速解决
- 删除特殊情况201处理程序和随后的GET对错误没有影响
- 延迟总是1.1分钟。我已经使用
console.time()
来确定延迟在65000ms范围内变化 - 延迟仅在此配置中出现。它不会出现在我们的开发设置中,因为我们的开发稍微简单一些
我所做的未经验证的假设:
- 一旦Nginx记录了一个请求,响应就会被鞠躬绑起来,并发送给客户一张手写的感谢信
- 这不是浏览器或jQuery中的错误
请原谅这个煞费苦心的细节,但我已经尽了最大努力消除了变量,目前,我可以放心地说,问题是以下之一:
- 宇宙物理结构中的一个缺陷
- 我们头脑感知模型中的一个缺陷
- 其他我们还没有考虑的事情
我希望获得第三名。有什么想法吗?
谜团解开!这是Content-Length
的标题,或者更确切地说,缺少一个@MaxDounin有一个正确的想法,我只是做得不够深入。
启用Django的django.middleware.http.ConditionalGetMiddleware
成功了。(此中间件设置Content-Length
标头。)