¿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.
- Retrofit ETAG y almacenamiento en caché
- Retrofit detectó un OkHttp no admitido en el error classpath en OKHttp 2.0
- OkHTTP y Picasso no funcionan juntos
- HTTPS no envía algunos encabezados de autenticación con Retrofit
- Android OkHttp, actualizar símbolo expirado
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...)
- OkHttp con pinzado de certificado
- Diferencia entre okhttp y httpurlconnection?
- Biblioteca de OkHttp - NetworkOnMainThreadException en la publicación simple
- Error retrofit.RetrofitError: java.io.EOFException para Android
- OkHTTP Actualiza la interfaz de usuario desde la devolución de llamada en cola
- Retrofit 2 tutorial ejemplo, pero GsonConverterFactory error de visualización "No se puede resolver el símbolo"
- Cómo convertir la respuesta de Okhttp en inputstream
- Android OkHttp cómo manejar ETag
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.