¿Qué causa "java.io.IOException: se restableció el flujo: CANCELAR" con okhttp y spdy?

Estoy experimentando con OKHttp (versión 2.0.0-RC2) y SPDY y viendo IOException: stream was reset: CANCEL bastante, tal vez el 10% o más de todas las solicitudes en algunas pruebas preliminares. Cuando utilizamos Apache HttpClient y https regulares no estábamos viendo ningún problema equivalente por lo que yo sepa. Estoy bastante seguro de que tampoco vemos nada equivalente con OkHttp cuando SPDY está deshabilitado ( client.setProtocols(ImmutableList.of(Protocol.HTTP_1_1)) ) pero no he hecho suficientes pruebas para estar 100% seguro.

Esta pregunta anterior ve a estas excepciones entre otras y el consejo que hay para ignorarlas, pero esto parece una locura: obtenemos una excepción al leer los datos del servidor, por lo que abortar el código de procesamiento de datos (que utiliza Jackson). Tenemos que hacer algo en estos casos. Podríamos reintentar la petición, por supuesto, pero a veces es una petición POST que no se puede volver a intentar, y si ya hemos comenzado a recibir datos del servidor, entonces es una buena apuesta que el servidor ya ha tomado la acción solicitada.

Idealmente hay alguna configuración del cliente y / o el servidor que podemos hacer para reducir la incidencia de estas excepciones, pero no entiendo SPDY lo suficientemente bien como para saber dónde comenzar a buscar o para asesorar a nuestro servidor-admin Equipo para empezar a buscar.

Rastro de la pila, en caso de que sea útil:

 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...) 

Su mejor opción es establecer un punto de interrupción en los dos lugares donde se asigna el código de error CANCEL: SpdyStream#closeInternal (línea 246) y SpdyStream#receiveRstStream (línea 304). Si puede poner un punto de interrupción aquí, puede capturar quién está cancelando su flujo y eso arrojará luz sobre el problema.

Si por alguna razón no puede adjuntar un depurador, puede instrumentar el código para imprimir un stacktrace cuando se alcancen esas líneas:

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

En cualquier caso, soy el autor de ese código y me encantaría ayudarle a resolver este problema.

Tuvimos este problema debido a los encabezados rotos http. El codificador androide Base64 de forma predeterminada añade nuevas líneas que rompieron nuestros encabezados de Autorización.

  • Cómo configurar el caché Http cuando se utiliza Volley con OkHttp?
  • Http sesión siempre se crea en la versión Android ModernHttpClient (okHttp1.5)
  • Retrofit 2.0 java.lang.IllegalStateException: Se esperaba BEGIN_ARRAY pero era STRING
  • Cómo agregar parámetros a api (http post) usando la biblioteca okhttp en Android
  • ¿Cómo obtener la URL redireccionada de OkHttp3?
  • ¿Cómo implementar Android Volley con OkHttp 2.0?
  • ¿Cuáles son los lugares correctos para los parámetros en OKHttp en una llamada de formulario de varias partes?
  • ¿Cómo obtener un cuerpo de respuesta para la excepción de actualización?
  • Cómo agregar un token de autenticación en el encabezado de la biblioteca Picasso
  • ¿Es posible inhabilitar los siguientes redireccionamientos en OkHttp 2.0?
  • Retrofit y OkHttpClient, catch timeout de conexión en el método de fallo
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.