java.net.HttpClient завершается с ошибкой EOFException при выполнении POST - PullRequest
0 голосов
/ 19 сентября 2019

У меня есть приложение, которое использует openjdk-11.0.1 java.net.HttpClient для создания многочастного POST-запроса к конечной точке REST (ish).Эта конечная точка блокирует ответ, когда выполняет какую-либо работу, а когда работа выполнена, она возвращает ответ.Природа этой конечной точки такова, что ответ может занять от 1 с до 1 d, поэтому это соединение может удерживаться в течение очень долгого времени.

Так или иначе, недавно я началчтобы столкнуться с приведенной ниже ошибкой, даже если процесс на целевом сервере все еще выполняется нормально.У кого-нибудь есть идеи о возможных причинах этой ошибки?

Caused by: java.util.concurrent.ExecutionException: java.io.IOException: HTTP/1.1 header parser received no bytes
    at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:395)
    at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1999)
    at com.paxata.perf.rdp.profile.DatasetProfiler.toJson(DatasetProfiler.java:190)
    ... 9 common frames omitted
Caused by: java.io.IOException: HTTP/1.1 header parser received no bytes
    at java.net.http/jdk.internal.net.http.common.Utils.wrapWithExtraDetail(Utils.java:293)
    at java.net.http/jdk.internal.net.http.Http1Response$HeadersReader.onReadError(Http1Response.java:657)
    at java.net.http/jdk.internal.net.http.Http1AsyncReceiver.checkForErrors(Http1AsyncReceiver.java:297)
    at java.net.http/jdk.internal.net.http.Http1AsyncReceiver.flush(Http1AsyncReceiver.java:263)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(SequentialScheduler.java:175)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
    at java.net.http/jdk.internal.net.http.HttpClientImpl$DelegatingExecutor.execute(HttpClientImpl.java:153)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:273)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:242)
    at java.net.http/jdk.internal.net.http.Http1AsyncReceiver.onReadError(Http1AsyncReceiver.java:506)
    at java.net.http/jdk.internal.net.http.Http1AsyncReceiver$Http1TubeSubscriber.onComplete(Http1AsyncReceiver.java:591)
    at java.net.http/jdk.internal.net.http.common.SSLTube$DelegateWrapper.onComplete(SSLTube.java:268)
    at java.net.http/jdk.internal.net.http.common.SSLTube$SSLSubscriberWrapper.complete(SSLTube.java:411)
    at java.net.http/jdk.internal.net.http.common.SSLTube$SSLSubscriberWrapper.onComplete(SSLTube.java:540)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper.checkCompletion(SubscriberWrapper.java:443)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper$DownstreamPusher.run1(SubscriberWrapper.java:322)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper$DownstreamPusher.run(SubscriberWrapper.java:261)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(SequentialScheduler.java:175)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:271)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:224)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper.outgoing(SubscriberWrapper.java:234)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader.processData(SSLFlowDelegate.java:467)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader$ReaderDownstreamPusher.run(SSLFlowDelegate.java:263)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(SequentialScheduler.java:175)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
    ... 3 common frames omitted
Caused by: java.io.EOFException: EOF reached while reading
    ... 21 common frames omitted

Вот создание моего HttpClient:

default HttpClient create() {
    final SSLContextBuilder sslContextBuilder;

    try {
        sslContextBuilder = new SSLContextBuilder().loadTrustMaterial(TrustSelfSignedStrategy.INSTANCE);
    } catch (NoSuchAlgorithmException | KeyStoreException e) {
        throw new RuntimeException("Unable to build SSLContext", e);
    }

    // PREVENTS HOST VALIDATION
    final Properties props = System.getProperties();
    props.setProperty("jdk.internal.httpclient.disableHostnameVerification", Boolean.TRUE.toString());

    // SHOULD PREVENT HOST VALIDATION
    final SSLParameters sslParams = new SSLParameters();
    sslParams.setEndpointIdentificationAlgorithm(null);

    try {
        final SSLContext sslContext = sslContextBuilder.build();
        ignoreExpiredCerts(sslContext);

        return HttpClient.newBuilder().version(Version.HTTP_1_1).sslContext(sslContext).sslParameters(sslParams)
            .build();
    } catch (KeyManagementException | NoSuchAlgorithmException e) {
        throw new RuntimeException("Unable to build HttpClient", e);
    }
}

private void ignoreExpiredCerts(final SSLContext sslContext) throws KeyManagementException {
    TrustManagerFactory tmf;

    try {
        tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    } catch (final NoSuchAlgorithmException e) {
        throw new RuntimeException("Unable to build HttpClient", e);
    }

    try {
        tmf.init((KeyStore) null);
    } catch (final KeyStoreException e) {
        throw new RuntimeException("Unable to build HttpClient", e);
    }

    final TrustManager[] trustManagers = tmf.getTrustManagers();
    final X509TrustManager origTrustmanager = (X509TrustManager) trustManagers[0];
    final AtomicBoolean logged = new AtomicBoolean(false);

    final TrustManager[] wrappedTrustManagers = new TrustManager[] { new X509TrustManager() {
        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return origTrustmanager.getAcceptedIssuers();
        }

        @Override
        public void checkClientTrusted(final X509Certificate[] certs, final String authType)
            throws CertificateException {
        origTrustmanager.checkClientTrusted(certs, authType);
        }

        @Override
        public void checkServerTrusted(final X509Certificate[] certs, final String authType)
            throws CertificateException {
        try {
            origTrustmanager.checkServerTrusted(certs, authType);
        } catch (final CertificateExpiredException e) {
            if (!logged.get()) {
            LOGGER.warn("Server certificate expired", e);
            logged.set(true);
            }
        } catch (final Exception e) {
            if (e.getCause() != null && e.getCause().getCause() != null
                && e.getCause().getCause() instanceof CertificateExpiredException) {
            if (!logged.get()) {
                LOGGER.warn("Server certificate expired", e.getCause().getCause());
                logged.set(true);
            }
            } else {
            throw e;
            }
        }
        }
    } };

    sslContext.init(null, wrappedTrustManagers, null);
}
...