我正在使用带有弹簧的色带的okhttp。 我希望在连接超时上重试另一个服务实例,但不会在读取超时时重试(原因很明显)。此重试将由自定义功能区重试处理程序处理。但要做到以上几点,我需要区分读取和连接超时。 okhttp的行为如下:
读取超时:
java.net.SocketTimeoutException: timeout
at okio.Okio$3.newTimeoutException(Okio.java:212)
at okio.AsyncTimeout.exit(AsyncTimeout.java:288)
at okio.AsyncTimeout$2.read(AsyncTimeout.java:242)
at okio.RealBufferedSource.indexOf(RealBufferedSource.java:325)
at okio.RealBufferedSource.indexOf(RealBufferedSource.java:314)
at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:210)
at okhttp3.internal.http.Http1xStream.readResponse(Http1xStream.java:184)
at okhttp3.internal.http.Http1xStream.readResponseHeaders(Http1xStream.java:125)
at okhttp3.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:775)
at okhttp3.internal.http.HttpEngine.access$200(HttpEngine.java:86)
at okhttp3.internal.http.HttpEngine$NetworkInterceptorChain.proceed(HttpEngine.java:760)
at okhttp3.internal.http.HttpEngine.readResponse(HttpEngine.java:613)
at okhttp3.RealCall.getResponse(RealCall.java:244)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:201)
at com.bluejeans.sample.test.OkHttpConnect$1.intercept(OkHttpConnect.java:25)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:190)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
at okhttp3.RealCall.execute(RealCall.java:57)
at com.bluejeans.sample.test.OkHttpConnect.main(OkHttpConnect.java:39)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at okio.Okio$2.read(Okio.java:140)
at okio.AsyncTimeout$2.read(AsyncTimeout.java:238)
... 16 more
连接超时:
java.net.SocketTimeoutException: connect timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at okhttp3.internal.Platform.connectSocket(Platform.java:121)
at okhttp3.internal.io.RealConnection.connectSocket(RealConnection.java:185)
at okhttp3.internal.io.RealConnection.buildConnection(RealConnection.java:170)
at okhttp3.internal.io.RealConnection.connect(RealConnection.java:111)
at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:187)
at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:123)
at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:93)
at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:296)
at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
at okhttp3.RealCall.getResponse(RealCall.java:243)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:201)
at com.bluejeans.sample.test.OkHttpConnect$1.intercept(OkHttpConnect.java:25)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:190)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
at okhttp3.RealCall.execute(RealCall.java:57)
at com.bluejeans.sample.test.OkHttpConnect.main(OkHttpConnect.java:39)
基于异常消息的决定似乎不是一个好主意。推荐的方法是什么?
答案 0 :(得分:0)
如果您不想依赖该消息,您还可以选择以下选项。但是它们都需要JUnit覆盖,因为OkHttp的开发人员可能会在将来改变它们的实现。
使用异常原因来决定如何处理请求:
try {
...
} catch (SocketTimeoutException e) {
if (e.getCause() != null && e.getCause() instanceof SocketTimeoutException) {
// read timeout
} else {
// socket timeout
}
}
循环堆栈跟踪:
try {
...
} catch (SocketTimeoutException e) {
boolean isConnectException = false;
for (StackTraceElement elem : e.getStackTrace()) {
if ("java.net.Socket".equals(elem.getClassName()) &&
"connect".equals(elem.getMethodName())) {
isConnectException = true;
break;
}
}
...
}