square / okhttp

Square’s meticulous HTTP client for the JVM, Android, and GraalVM.
https://square.github.io/okhttp/
Apache License 2.0
45.77k stars 9.15k forks source link

Okhttp canceled the request on its own #8509

Open feilaobinge opened 1 month ago

feilaobinge commented 1 month ago

I use okhttp 4.12.0 to upload images to K8S. It took 40 minutes to upload the file when more than half of the network bandwidth was occupied. According to the Kubernetes logs, one of the image upload requests was canceled by okhttp. The error stack of Okhttp is TimeoutException. Sorry, this is an occasional question. So no failed test cases are provided.

feilaobinge commented 1 month ago

com.xxx.ThrowableFacade:timeout at okio.SocketAsyncTimeout.newTimeoutException(JvmOkio.kt:146) ~[okio-jvm-3.6.0.jar:?] at okio.AsyncTimeout.access$newTimeoutException(AsyncTimeout.kt:161) ~[okio-jvm-3.6.0.jar:?] at okio.AsyncTimeout$sink$1.write(AsyncTimeout.kt:342) ~[okio-jvm-3.6.0.jar:?] at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.kt:256) ~[okio-jvm-3.6.0.jar:?] at okio.RealBufferedSink.write(RealBufferedSink.kt:147) ~[okio-jvm-3.6.0.jar:?] at okhttp3.internal.http1.Http1ExchangeCodec$KnownLengthSink.write(Http1ExchangeCodec.kt:279) ~[okhttp-4.12.0.jar:?] at okio.ForwardingSink.write(ForwardingSink.kt:29) ~[okio-jvm-3.6.0.jar:?] at okhttp3.internal.connection.Exchange$RequestBodySink.write(Exchange.kt:223) ~[okhttp-4.12.0.jar:?] at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.kt:256) ~[okio-jvm-3.6.0.jar:?] at okio.RealBufferedSink.writeAll(RealBufferedSink.kt:195) ~[okio-jvm-3.6.0.jar:?] at okhttp3.RequestBody$Companion$asRequestBody$1.writeTo(RequestBody.kt:167) ~[okhttp-4.12.0.jar:?] at okhttp3.MultipartBody.writeOrCountBytes(MultipartBody.kt:157) ~[okhttp-4.12.0.jar:?] at okhttp3.MultipartBody.writeTo(MultipartBody.kt:93) ~[okhttp-4.12.0.jar:?] at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.kt:62) ~[okhttp-4.12.0.jar:?] at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) ~[okhttp-4.12.0.jar:?] at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:34) ~[okhttp-4.12.0.jar:?] at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) ~[okhttp-4.12.0.jar:?] at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95) ~[okhttp-4.12.0.jar:?] at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) ~[okhttp-4.12.0.jar:?] at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83) ~[okhttp-4.12.0.jar:?] at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) ~[okhttp-4.12.0.jar:?] at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76) ~[okhttp-4.12.0.jar:?] at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) ~[okhttp-4.12.0.jar:?] at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201) ~[okhttp-4.12.0.jar:?] at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154) ~[okhttp-4.12.0.jar:?]

JakeWharton commented 1 month ago

This is a normal timeout which occurs due to the timeout values on the OkHttpClient which are either the default values or your overridden ones. The solution is to bump the values, assuming you want to tolerate a longer delay before being notified of a congested/absent network, or to re-enqueue the work to happen at a later time using the next layer up in your application architecture.

feilaobinge commented 1 month ago

This is a normal timeout which occurs due to the timeout values on the OkHttpClient which are either the default values or your overridden ones. The solution is to bump the values, assuming you want to tolerate a longer delay before being notified of a congested/absent network, or to re-enqueue the work to happen at a later time using the next layer up in your application architecture.

Is there a recommended timeout value?

JakeWharton commented 1 month ago

I'd say our defaults are the generally-recommended values. You know more about your application than we do. Some mobile applications want higher timeouts to tolerate slower mobile networks and intermittent radio connectivity loss like tunnels and such. Some server applications want lower timeouts as they want to respond to their caller quickly. Additionally, who you're talking to also matters (which again only you know about). If you're talking to a server halfway around the world then you need larger timeouts to accommodate the fact that it will simple take a long time for the many roundtrips of the underlying TCP connection to complete. If you're talking over fiber to a server in the same datacenter then you don't need to wait to detect link failures.