什么原因导致 okhttp 和 spdy "java.io.IOException: stream was reset: CANCEL"?



我正在试验OKHttp (2.0.0-RC2版本)和SPDY,并且看到IOException: stream was reset: CANCEL相当多,在一些初步测试中可能占所有请求的10%或更多。当使用Apache HttpClient和常规https时,据我所知,我们没有看到任何等效的问题。我很确定,当SPDY被禁用(client.setProtocols(ImmutableList.of(Protocol.HTTP_1_1)))时,我们也没有看到任何与OkHttp等效的东西,但我还没有做足够的测试来100%确信。

前面的问题看到了这些异常,建议忽略它们,但这似乎很疯狂:我们在从服务器读取数据时得到一个异常,所以我们中止数据处理代码(使用Jackson)。在这种情况下,我们需要做一些事情。当然,我们可以重试请求,但有时这是一个POST请求,不可重试,如果我们已经开始从服务器接收数据,那么很可能服务器已经采取了请求的操作。

理想情况下,我们可以对客户端和/或服务器进行一些配置,以减少这些异常的发生率,但我不太了解SPDY,甚至不知道从哪里开始寻找或建议我们的服务器管理团队开始寻找。

堆栈跟踪,如果有帮助的话:

java.io.IOException: stream was reset: CANCEL
  at com.squareup.okhttp.internal.spdy.SpdyStream$SpdyDataSource.checkNotClosed(SpdyStream.java:442)
  at com.squareup.okhttp.internal.spdy.SpdyStream$SpdyDataSource.read(SpdyStream.java:344)
  at com.squareup.okhttp.internal.http.SpdyTransport$SpdySource.read(SpdyTransport.java:273)
  at okio.RealBufferedSource.exhausted(RealBufferedSource.java:60)
  at okio.InflaterSource.refill(InflaterSource.java:96)
  at okio.InflaterSource.read(InflaterSource.java:62)
  at okio.GzipSource.read(GzipSource.java:80)
  at okio.RealBufferedSource$1.read(RealBufferedSource.java:227)
  at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.loadMore(UTF8StreamJsonParser.java:174)
  at com.fasterxml.jackson.core.base.ParserBase.loadMoreGuaranteed(ParserBase.java:431)
  at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._finishString2(UTF8StreamJsonParser.java:2111)
  at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._finishString(UTF8StreamJsonParser.java:2092)
  at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.getText(UTF8StreamJsonParser.java:275)
  at com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer.deserializeObject(JsonNodeDeserializer.java:205)
  at com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer.deserializeArray(JsonNodeDeserializer.java:230)
  at com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer.deserializeObject(JsonNodeDeserializer.java:202)
  at com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer.deserialize(JsonNodeDeserializer.java:58)
  at com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer.deserialize(JsonNodeDeserializer.java:15)
  at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:2765)
  at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:1546)
  at com.fasterxml.jackson.core.JsonParser.readValueAsTree(JsonParser.java:1363)
  at (application-level code...)

您最好的选择是在分配CANCEL错误代码的两个地方设置一个断点:即SpdyStream#closeInternal(第246行)和SpdyStream#receiveRstStream(第304行)。如果你可以在这里设置一个断点,你可以捕获正在取消你的流,这将阐明问题。

如果由于某种原因您不能附加调试器,您可以对代码进行调试,以便在到达这些行时打印堆栈跟踪:

new Exception("SETTING ERROR CODE TO " + errorCode).printStackTrace();

无论哪种情况,我都是该代码的作者,我很乐意帮助您解决这个问题。

有同样的问题,这是网络连接超时的结果,这是从web服务下载一个大文件的结果我有我的超时设置为2分钟,所以我把它改为5分钟,它解决了我的问题

val  okkHttpclient = OkHttpClient.Builder()
   .connectTimeout(5, TimeUnit.MINUTES)
    .writeTimeout(5, TimeUnit.MINUTES) // write timeout
    .readTimeout(5, TimeUnit.MINUTES) // read timeout
    .addInterceptor(networkConnectionInterceptor)
    .build()

我们有这个问题,因为破碎的http头。android的Base64编码器默认会添加换行符,这会破坏我们的授权头。

最新更新