【发布时间】:2021-08-25 05:21:06
【问题描述】:
我们正在使用 OkHttp3 (v4.9.1) 从 Spring Boot 应用程序以高度并发的方式建立 h2c(没有 TLS 的 HTTP/2)连接。为此,我们使用以下方法缩小了支持的协议范围:
builder.protocols(List.of(Protocol.H2_PRIOR_KNOWLEDGE))
建立连接通常可以正常工作,并且使用 HTTP/2 流而不是专用连接。然而,我们观察到当服务器(基于 nginx,单节点,单地址)在达到一定数量的请求后关闭连接(如其keepalive_request 选项所指示的那样)时,会出现零星的错误突发。发生这种情况时,OkHttp 似乎不会尝试重试连接,而只是向调用者抛出异常:
okhttp3.internal.http2.StreamResetException: stream was reset: REFUSED_STREAM
at okhttp3.internal.http2.Http2Stream.takeHeaders(Http2Stream.kt:148)
at okhttp3.internal.http2.Http2ExchangeCodec.readResponseHeaders(Http2ExchangeCodec.kt:96)
at okhttp3.internal.connection.Exchange.readResponseHeaders(Exchange.kt:106)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.kt:79)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:34)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at org.example.OkHttpAutoConfiguration.lambda$authenticate$3(OkHttpAutoConfiguration.java:95)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)
[...]
请求是这样发起的:
httpClient.newCall(buildRequest(uri)).execute()
处理这些错误的推荐方法是什么?
是否有一个选项(我们可能错过了)让 OkHttp 对应用程序透明地处理这个问题?
【问题讨论】: