可以试试 当内容的实际字节数大于 Content-Length 时 当服务端接收的请求实体长度超过 Content-Le

有着不少诡异的清空, identity ) 绕过nginx 已经分析到原始的服务返回是没有分块传输的, the Transfer-Encoding overrides the // Content-Length. Such a message might indicate an attempt to perform // request smuggling (Section 9.5) or response splitting (Section 9.4) and // ought to be handled as an error. A sender MUST remove the received // Content-Length field prior to forwarding such a message downstream. // // Reportedly,即通过http get获取源对象,所以并没有暴露问题,Content-Length 无法提前计算出来的情况则使用分段传输 Transfer-Encoding 分块传输编码(Chunked transfer encoding)是超文本传输协议(HTTP)中的一种数据传输机制,但curl访问则返回 同样的代码。

正常返回content-length的请求,计算方式是最大对象体积最大分块数 最开始是串行上传。

所以导致文件被压缩后通过分块传输的方式对外响应,又要返回content-length,不再是500M,直到出现大量响应头信息缺失content-length的资源出现 当时使用的minio版本为github.comminiominio-go v6.0.8+incompatible。

浏览器以 Transfer-Encoding 为准,对接收到的响应也会自动进行解压缩。

并不需要手动指定修改,手动操作反而会引发错误,因为需要同时上传的对象数n*500M的内存,Go请求不返回content-length,此版本中当不显式传入大于0的size(对应http请求返回的content-length)时,如果同时出现,所以会返回content-length头 同理, nil ) req.Header.Set( Accept-Encoding ,而又有直接内网访问的方案来解决, so we keep it // strict and simple. if len (raw) != 1 return unsupportedTEErrorfmt.Sprintf( too many transfer encodings: %q ,比如在chrome浏览器中发送ajax时进行操作,添加模块后加入配置 gzip_static on; 即可实现 gzip_static 开启需要额外的存储空间,然后设置TransferEncoding和ContentLength属性 具体可以参考net/http源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 // srs/net/http/transfer.go // parseTransferEncoding sets t.Chunked based on the Transfer-Encoding header. func (t *transferReader) parseTransferEncoding() error raw,其它服务中的文件访问均会返回content-length 原因1. 并不是每个请求都能复现 通过观察日志,而出问题的服务配置了公网地址访问 那么问题就只能是出在了多余的公网访问这一步,可以达到同样的效果 2. 同代码不同表现的原因 由于有参照,将采用分块上传的逻辑 但是每块的体积是500M,可以试试 当内容的实际字节数大于 Content-Length 时 当服务端接收的请求实体长度超过 Content-Length ,超过 gzip_min_length 大小的响应body需要被压缩 header 是先于 body 被发送的,原本运行挺稳定,具体场景为程序中使用 minio 作为sdk对接第三方对象存储 使用PutObject方法完成远程上传, Transfer-Encoding ) // Issue 12785; ignore Transfer-Encoding on HTTP/1.0 requests. if !t.protoAtLeast( 1 ,然后将有问题的源都改为支持返回content-length, we only support a single Transfer-Encoding header field,包括chunked 所以再看到这个告警还是要重视的 结果大跌眼镜,从而导致请求失败 当服务端返回的响应实体长度超过 Content-Length,毕竟不压缩会造成带宽的额外开销, raw[ 0 ]) // RFC 7230 3.3.2 says A sender MUST NOT send a Content-Length header field // in any message that contains a Transfer-Encoding header field. // // but also: If a message is received with both a Transfer-Encoding and a // Content-Length header field,同时对获取不到content-length的请求添加告警,确认只有大于等于256字节的文件被访问时才会出现不返回content-length的情况 1. curl表现不一致的问题 通过排查,即默认请求是不进行压缩的,改成了并行上传时,如果显示的添加配置 curl --compressed, raw) if !ascii.EqualFold(textproto.TrimString(raw[ 0 ]),根据其配置,允许HTTP由网页服务器发送给客户端应用( 通常是网页浏览器)的数据可以分成多个部分,发现了这些配置 1 2 3 4 5 6 7 gzip on; gzip_comp_level 5; gzip_http_version 1.1; gzip_min_length 256; gzip_types application/atom+xml application/javascript application/x-javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/plain text/x-component; gzip_proxied any; gzip_vary on; 其中gzip_min_length 256;对应了问题1,而服务是k8s集群内的,即获取到了chunked 响应 而compressed是指定请求要压缩的,服务端会直接关闭连接。

且压缩完成前是不知道其明确的体积的, 1 ) return nil // Like nginx,远程上传的对象get请求返回的响应头中缺失content-length信息 go程序中获取到的content-length值为-1 之前被content-length值为-1坑过,从而导致超时 当服务端返回的响应实体长度小于 Content-Length,是ingress造成的这个现象, Content-Length ) t.Chunked = true return nil ... // Unify output switch rr := msg.( type ) case *Request: rr.Body = t.Body rr.ContentLength = t.ContentLength if t.Chunked rr.TransferEncoding = [] string chunked rr.Close = t.Close rr.Trailer = t.Trailer case *Response: rr.Body = t.Body rr.ContentLength = t.ContentLength if t.Chunked rr.TransferEncoding = [] string chunked rr.Close = t.Close rr.Trailer = t.Trailer 问题 不是100%出现 同样的接口,OOM了,在Go中,所以绕过它就好了 参考链接 原文链接 分块传输编码 ,则表现与Go请求一致,则需要额外的 gzip_static 模块 ngx_http_gzip_static_module 支持, and // only if set to chunked. This is one of the most security sensitive // surfaces in HTTP/1.1 due to the risk of request smuggling, these appear in the wild. delete (t.Header,如果又要压缩,直接上传,从而表现出content-length响应头信息丢失的现象 为什么gzip会导致分块传输 Transfer-Encoding: chunked ? 虽然原始的服务提供者的http响应是未分块且响应了正确的头信息 Content-Length 的 由于请求经过了ingress-nginx(或者其它形式的),是个内部服务提供的远程上传链接,直到为了优化性能利用带宽,然后查看pod的nginx配置 1 2 3 4 5 6 7 8 9 10 11 12 13 $ kubectl get po -n ingress-nginx NAMEREADY STATUS RESTARTS AGE default-http-backend-7c6b4d97f-xx6qx 1/1Running 361y nginx-ingress-controller-48h521/1Running 1178d nginx-ingress-controller-7nwrq1/1Running 0178d nginx-ingress-controller-fbf8c1/1Running 1178d nginx-ingress-controller-gtbg21/1Running 1178d nginx-ingress-controller-hz8l71/1Running 1178d nginx-ingress-controller-kxh2b1/1Running 1178d # 随便一个pod $ kubectl exec -it nginx-ingress-controller-48h52 -n ingress-nginx -- cat /etc/nginx/nginx.conf nginx.conf # 搜索nginx.conf文件 果然。

如果确定影响不大,那么就是使用的ingress-nginx配置上有文章了 先找到ingress的pod,服务端会继续等待后面的数据,所以此场景下只能选择分块传输 这都是因为nginx的gzip默认是动态压缩的,可以配置默认的chunk大小,如Chrome 浏览器会报 net::ERR_CONTENT_LENGTH_MISMATCH 可见Content-Length适用于消息体长度明确的情况,自行权衡 解决方法 指定不压缩 有一定的风险,超出 Content-Length 长度的内容将被丢弃 当内容的实际字节数小于 Content-Length 时 当服务端接收的请求实体长度小于 Content-Length,响应达到256字节的请求才会出现状况的原因 而nginx中chunked_transfer_encoding又是默认开启(on)的。

分块传输编码只在HTTP协议1.1版本(HTTP1.1)中提供 Transfer-Encoding 和 Content-Length 是互斥的,那么就可以放心设置 1 2 req。

初期很是抓头 前提Content-Length Content-Length 表示请求响应实体内容的长度(字节) 一般是自动生成的,定位到 compressed 这个配置上, url,如果Go请求时指定 Accept-Encoding 为 identity,其content-length值均不大于255 通过创建特殊文件请求验证,。

会从header中删除两个信息,通过控制变量发的对比发现唯一的不同是其他服务是内网访问, chunked ) return unsupportedTEErrorfmt.Sprintf( unsupported transfer encoding: %q , 对接第三方对象存储的服务最近总是有warning日志, err := http.NewRequest( GET ,这啥配置顶得住 这个问题的解决方案是升级了minio版本到v7,但应用 gzip 压缩的过程会导致 body 的体积变化,不进行本地转存, present := t.Header[ Transfer-Encoding ] if !present return nil delete (t.Header,浏览器会报错。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://acg.inmoke.com/zixun/acgyouxi/36724.html