Solrj client will retry requests on SSLException with a suppressed SocketException (very likely a hard-closed socket connection)

This commit is contained in:
Dawid Weiss 2020-01-03 14:09:27 +01:00
parent 2bab5ea442
commit f789e053d2
3 changed files with 29 additions and 12 deletions

View File

@ -213,6 +213,9 @@ Other Changes
* SOLR-14091: Remove deprecated soLingerTime when configuring Jetty connector (Matthias Krueger via Kevin Risden)
* SOLR-13778: Solrj client will retry requests on SSLException with a suppressed SocketException
(very likely a hard-closed socket connection).
================== 8.4.0 ==================
Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release.

View File

@ -28,7 +28,6 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.common.cloud.ClusterProperties;
@ -41,7 +40,6 @@ import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
@SolrTestCaseJ4.SuppressSSL
public class LegacyCloudClusterPropTest extends SolrCloudTestCase {
@BeforeClass

View File

@ -20,11 +20,13 @@ import java.io.IOException;
import java.io.InterruptedIOException;
import java.lang.invoke.MethodHandles;
import java.net.ConnectException;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
import javax.net.ssl.SSLException;
@ -34,6 +36,7 @@ import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.RequestWrapper;
import org.apache.http.protocol.HttpContext;
import org.apache.solr.client.solrj.util.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -62,7 +65,7 @@ public class SolrHttpRequestRetryHandler implements HttpRequestRetryHandler {
protected SolrHttpRequestRetryHandler(final int retryCount, final Collection<Class<? extends IOException>> clazzes) {
super();
this.retryCount = retryCount;
this.nonRetriableClasses = new HashSet<Class<? extends IOException>>();
this.nonRetriableClasses = new HashSet<>();
for (final Class<? extends IOException> clazz : clazzes) {
this.nonRetriableClasses.add(clazz);
}
@ -108,17 +111,12 @@ public class SolrHttpRequestRetryHandler implements HttpRequestRetryHandler {
log.debug("Do not retry, over max retry count");
return false;
}
if (this.nonRetriableClasses.contains(exception.getClass())) {
if (!isRetriable(exception)) {
log.debug("Do not retry, non retriable class {}", exception.getClass().getName());
return false;
} else {
for (final Class<? extends IOException> rejectException : this.nonRetriableClasses) {
if (rejectException.isInstance(exception)) {
log.debug("Do not retry, non retriable class {}", exception.getClass().getName());
return false;
}
}
}
final HttpClientContext clientContext = HttpClientContext.adapt(context);
final HttpRequest request = clientContext.getRequest();
@ -135,7 +133,25 @@ public class SolrHttpRequestRetryHandler implements HttpRequestRetryHandler {
log.debug("Do not retry, no allow rules matched");
return false;
}
private boolean isRetriable(IOException exception) {
// Workaround for "recv failed" issue on hard-aborted sockets on Windows
// (and other operating systems, possibly).
// https://issues.apache.org/jira/browse/SOLR-13778
if (exception instanceof SSLException &&
Arrays.stream(exception.getSuppressed()).anyMatch((t) -> t instanceof SocketException)) {
return true;
}
// Fast check for exact class followed by slow-check with instanceof.
if (nonRetriableClasses.contains(exception.getClass())
|| nonRetriableClasses.stream().anyMatch(rejectException -> rejectException.isInstance(exception))) {
return false;
}
return true;
}
public int getRetryCount() {
return retryCount;
}