前言:我正在使用s3boto作为默认存储后端的amazon ec2实例上运行nginx+gunicorn+django。我是自由层。ec2安全组允许:http、ssh和&https。
我正在尝试发送一个包含单个元素的多部分/表单数据请求:照片。当试图上传照片时,iPhone(请求的来源)会挂起。这张照片的大小约为9.5 MB。
当我检查nginx-access.logs:时
"POST/myUrl/HTTP/1.1"400 5"-"…
当我检查nginx-error.logs:
[error] 5562#0: *1 readv() failed (104: Connection reset by peer) while reading upstream, client: my.ip.addr.iphone, server: default, request: "POST /myUrl/ HTTP/1.1", upstream: "http://127.0.0.1:8000/myUrl/", host: "ec2-my-server-ip-addr.the-location-2.compute.amazonaws.com"
[info] 5562#0: *1 client my.ip.addr.iphone closed keepalive connection
我真的不明白为什么会发生这种事。。。我已经尝试更改/etc/nginx/sites-available/default超时设置。。。
server { ...
client_max_body_size 20M;
client_body_buffer_size 20M;
location / {
keepalive_timeout 300;
proxy_read_timeout 300;
}
}
有什么想法吗?
EDIT:在IRC上多谈了一点之后,他的问题是403本身,而不是nginx错误。下面留下我对nginx错误的评论,以防有一天其他人偶然发现。
上周我遇到了这个问题,花了很长时间试图弄清楚发生了什么https://github.com/benoitc/gunicorn/issues/872
基本上,django一看到标头,就知道请求没有经过身份验证。它不需要等待大型请求体完成上传;它立即做出响应,gunicorn随即关闭连接。nginx不断发送数据,最终结果是gunicorn向nginx发送了一个RST包。一旦发生这种情况,nginx就无法恢复,它没有从gunicorn/django发送实际响应,而是发送了一个502坏网关。
我最终放入了一个中间件,它访问django请求中的几个字段,确保在django发送响应之前下载整个请求体:
checker = re.compile(feed_url_regexp)
class AccessPostBodyMiddleware:
def process_request(self, request):
if checker.match(request.path.lstrip('/')) is not None:
# just need to access the request info here
# not sure which one of these actually does the trick.
# This will download the entire request,
# fixing this random issue between gunicorn and nginx
_ = request.POST
_ = request.REQUEST
_ = request.body
return None
但是,我无法控制客户。既然你这样做了(以你的iphone应用程序的形式),也许你可以找到一种方法来处理502坏网关。这将使您的应用程序不必发送两次整个请求。