我们在Go 1.17rc2版本的httputil.ReverseProxy前面运行了一个Go go1.17rc2版本的net/http.Server。我们遇到了奇怪的ErrCodeProtocol流错误,所以我们停止使用捆绑的x/net/http2,并将其切换为显式使用x/net/http2(通过http2.ConfigureTransports和http2.ConfigureServer,因此不会使用捆绑的版本)。
我们的x/net git版本是golang/net@aaa1db6,这是今天的主分支。
我们最初收到的日志不足以告诉我们问题出在哪里:
2021/08/10 14:07:20 http: proxy error: stream error: stream ID 1293155; PROTOCOL_ERROR
2021/08/10 14:07:20 http: proxy error: stream error: stream ID 1293157; PROTOCOL_ERROR
但是在本地修改它,添加一些http2.Server中返回协议错误的路径上的expvar计数器后,我们发现问题出在这里:
https://github.com/golang/net/blob/aaa1db679c0d7765d2b1cb1f92cac8ebf4d94c53/http2/server.go#L1835
// http://tools.ietf.org/html/rfc7540#section-5.1.2
// [...] Endpoints MUST NOT exceed the limit set by their peer. An
// endpoint that receives a HEADERS frame that causes their
// advertised concurrent stream limit to be exceeded MUST treat
// this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR
// or REFUSED_STREAM.
if sc.curClientStreams+1 > sc.advMaxStreams {
if sc.unackedSettings == 0 {
// They should know better.
return streamError(id, ErrCodeProtocol)
}
因此,Go http2客户端(Transport)和/或服务器在其并发/最大流计算上出现了错误。
可能有趣的是:后端(ReverseProxy的Transport所击中的http2.Server)有非常长的运行时间的http.Handlers(例如:几天或几周长)。这也许可以解释为什么这个bug没有被更多人报告。
我没有看到最近的提交表明这是一个回归。这个服务器是新的,所以我也不能说它以前是否工作过。
cc @neild@bcmills@fraenkel@dmitshur@dsnet@josharian
6条答案
按热度按时间vm0i2vca1#
possible? #42777
o4tp2gmn2#
啊,是的。这可能是我们遇到的问题。
e5nszbig3#
CC @neild.
ecr0jaav4#
https://golang.org/cl/347033提到了这个问题:
http2: make Transport not reuse conns after a stream protocol error
nafvub8i5#
https://golang.org/cl/356978提到了这个问题:
[internal-branch.go1.16-vendor] http2: make Transport not reuse conns after a stream protocol error
myss37ts6#
https://golang.org/cl/357673提到了这个问题:
[internal-branch.go1.17-vendor] http2: make Transport not reuse conns after a stream protocol error