首页 > 解决方案 > 间歇性接收连接重置异常

问题描述

当服务器响应时间超过 4 分钟时,我收到“连接重置”异常。该服务直到上周都运行良好,但现在我间歇性地面临这个问题。

我使用 OkHttpClient 连接到外部服务。OkHttpClient 中的所有超时都配置为 0(零),因此永远不会发生连接和读取超时。当我尝试用 curl 发出相同的请求时,我成功地得到了响应。我什至尝试将 curl 与 java 以及 REST 模板一起使用,但仍然面临同样的问题。

这是异常的完整堆栈跟踪。

javax.net.ssl.SSLException: java.net.SocketException: Connection reset
    at sun.security.ssl.Alert.createSSLException(Alert.java:127) ~[na:1.8.0_271]
    at sun.security.ssl.TransportContext.fatal(TransportContext.java:353) ~[na:1.8.0_271]
    at sun.security.ssl.TransportContext.fatal(TransportContext.java:296) ~[na:1.8.0_271]
    at sun.security.ssl.TransportContext.fatal(TransportContext.java:291) ~[na:1.8.0_271]
    at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1453) ~[na:1.8.0_271]
    at sun.security.ssl.SSLSocketImpl.access$400(SSLSocketImpl.java:75) ~[na:1.8.0_271]
    at sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:931) ~[na:1.8.0_271]
    at okio.Okio$2.read(Okio.java:140) ~[okio-1.15.0.jar:na]
    at okio.AsyncTimeout$2.read(AsyncTimeout.java:237) ~[okio-1.15.0.jar:na]
    at okio.RealBufferedSource.indexOf(RealBufferedSource.java:354) ~[okio-1.15.0.jar:na]
    at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:226) ~[okio-1.15.0.jar:na]
    at okhttp3.internal.http1.Http1Codec.readHeaderLine(Http1Codec.java:215) ~[okhttp-3.12.0.jar:na]
    at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:189) ~[okhttp-3.12.0.jar:na]
    at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88) ~[okhttp-3.12.0.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.0.jar:na]
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45) ~[okhttp-3.12.0.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.0.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[okhttp-3.12.0.jar:na]
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93) ~[okhttp-3.12.0.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.0.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[okhttp-3.12.0.jar:na]
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) ~[okhttp-3.12.0.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.0.jar:na]
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126) ~[okhttp-3.12.0.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.0.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[okhttp-3.12.0.jar:na]
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254) ~[okhttp-3.12.0.jar:na]
    at okhttp3.RealCall.execute(RealCall.java:92) ~[okhttp-3.12.0.jar:na]
    at com.walmart.samsclub.payment.ccpa.service.services.CCPAExternalWSClient.processRequest(CCPAExternalWSClient.java:56) ~[classes/:na]
    at com.walmart.samsclub.payment.ccpa.service.services.CCPASamsPaymentService.lambda$0(CCPASamsPaymentService.java:70) [classes/:na]
    at java.util.ArrayList.forEach(ArrayList.java:1259) ~[na:1.8.0_271]
    at com.walmart.samsclub.payment.ccpa.service.services.CCPASamsPaymentService.sendRequestToPaymentService(CCPASamsPaymentService.java:66) [classes/:na]
    at com.walmart.samsclub.payment.ccpa.service.scheduler.CCPATicketUpdateSchedulerJob.updateMembershipInfo(CCPATicketUpdateSchedulerJob.java:190) ~[classes/:na]
    at com.walmart.samsclub.payment.ccpa.service.scheduler.CCPATicketUpdateSchedulerJob.scheduleTaskUsingCronExpression(CCPATicketUpdateSchedulerJob.java:115) ~[classes/:na]
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_271]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_271]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_271]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_271]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_271]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_271]
    at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_271]
    Suppressed: java.net.SocketException: Broken pipe (Write failed)
        at java.net.SocketOutputStream.socketWrite0(Native Method) ~[na:1.8.0_271]
        at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111) ~[na:1.8.0_271]
        at java.net.SocketOutputStream.write(SocketOutputStream.java:155) ~[na:1.8.0_271]
        at sun.security.ssl.SSLSocketOutputRecord.encodeAlert(SSLSocketOutputRecord.java:83) ~[na:1.8.0_271]
        at sun.security.ssl.TransportContext.fatal(TransportContext.java:384) ~[na:1.8.0_271]
        ... 41 common frames omitted
Caused by: java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:210) ~[na:1.8.0_271]
    at java.net.SocketInputStream.read(SocketInputStream.java:141) ~[na:1.8.0_271]
    at sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:475) ~[na:1.8.0_271]
    at sun.security.ssl.SSLSocketInputRecord.readHeader(SSLSocketInputRecord.java:469) ~[na:1.8.0_271]
    at sun.security.ssl.SSLSocketInputRecord.bytesInCompletePacket(SSLSocketInputRecord.java:69) ~[na:1.8.0_271]
    at sun.security.ssl.SSLSocketImpl.readApplicationRecord(SSLSocketImpl.java:1228) ~[na:1.8.0_271]
    at sun.security.ssl.SSLSocketImpl.access$300(SSLSocketImpl.java:75) ~[na:1.8.0_271]
    at sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:915) ~[na:1.8.0_271]
    ... 36 common frames omitted

OkHttpClient 设置配置代码

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
   throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
}
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { trustManager }, new java.security.SecureRandom());
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
OkHttpClient.Builder builder = new OkHttpClient().newBuilder();

builder.connectTimeout(0, TimeUnit.HOURS);
builder.readTimeout(0, TimeUnit.HOURS);
builder.writeTimeout(0, TimeUnit.HOURS);
OkHttpClient okHttpClient = builder.sslSocketFactory(sslSocketFactory, trustManager).build();
logger.debug("OkHttpClient created successfully");
return okHttpClient;

调用函数

public Response processRequest(String queryParam, Headers headers, RequestBody body, HttpMethod method) {
        Response res = null;
        try {

            Request request = buldRequest(queryParam, headers, body, method);
            String requestBody = bodyToString(request);
            logger.info("Request triggered {}", request.toString());
            if (StringUtils.isNotBlank(requestBody)) {
                logger.info("Request body {}", requestBody);
            }

            Call call = client.newCall(request);
            res = call.execute();

            if (res != null && !res.isSuccessful()) {
                String responseBodyString = res.peekBody(Long.MAX_VALUE).string();
                logger.error("The request was not successfull and the response code received id {} and body {}", res.code(), responseBodyString);
            }
        }
        catch (IOException e) {
            logger.error("Error while parsing data", e);
        }
        catch (Exception e) {
            logger.error("Error occured while connecting to extenal service", e);
        }

        return res;
    }

标签: javaspringspring-bootokhttp

解决方案


推荐阅读