HTTP 403 错误 + "readv() failed (104: Connection reset by peer) while reading upstream"



前言:我正在使用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坏网关。这将使您的应用程序不必发送两次整个请求。

最新更新