Skip to content

Commit ee61151

Browse files
committed
core: drop non-blocking DNS resolver from S3ClientCache
S3ClientCache opted the AWS SDK Netty async client into a non-blocking DNS resolver, gated on a hardcoded probe for the unrelocated class io.netty.resolver.dns.DnsAddressResolverGroup. On the Spark 4 / Core ETL driver bundle this probe is misleading: Spark and Hadoop put the unrelocated class on the classpath, so the probe returns true, but the active AWS SDK comes from iceberg-aws-bundle, whose NettyNioAsyncHttpClient -> AwaitCloseChannelPoolMap -> BootstrapProvider calls DnsResolverLoader, which is relocated to org.apache.iceberg.aws.shaded.io.netty.resolver.dns -- a class the bundle omits. Enabling non-blocking DNS then fails when the first connection pool/bootstrap is created. Remove the setting entirely and always use the SDK default (blocking) resolver. The benefit is negligible for this workload: the S3 backup reader goes through a single (or few) bucket host(s) per job with long-lived cached clients, keep-alive, and connection pooling, so DNS is resolved at connection creation and then cached by the JVM/Netty -- steady-state lookups are rare. Dropping it removes the relocation/ missing-class fragility for no measurable loss and shrinks the surface area to test across the OSS, aggregate, and prod-parity packaging shapes. This deletes the class-name constant, the availability field and probe helpers, the conditional builder branch, and the dns=nonBlocking cache-key suffix, and removes the now-defunct test plus its classpath helper. Netty relocation in the driver bundles remains correct and is retained. Revisit only if a future workload reads across many distinct S3 hosts or runs where DNS is slow.
1 parent 0a5245d commit ee61151

2 files changed

Lines changed: 2 additions & 53 deletions

File tree

cassandra-analytics-core/src/main/java/org/apache/cassandra/spark/data/S3ClientCache.java

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ public final class S3ClientCache
6868
static final int CONNECTION_TIMEOUT_SECONDS = 5;
6969
static final int READ_TIMEOUT_SECONDS = 120;
7070
static final int CONNECTION_MAX_IDLE_TIME_SECONDS = 60;
71-
static final String NETTY_DNS_RESOLVER_CLASS = "io.netty.resolver.dns.DnsAddressResolverGroup";
72-
private static final boolean NON_BLOCKING_DNS_RESOLVER_AVAILABLE = isClassAvailable(NETTY_DNS_RESOLVER_CLASS);
7371
private static volatile boolean loggedTaskSlotSource = false;
7472

7573
// Separate caches for different client types
@@ -221,7 +219,7 @@ private static String getAsyncCacheKey(S3ClientConfig config, ResolvedAsyncHttpC
221219
+ "|connectTimeout=" + CONNECTION_TIMEOUT_SECONDS
222220
+ "|readTimeout=" + READ_TIMEOUT_SECONDS
223221
+ "|idleTime=" + CONNECTION_MAX_IDLE_TIME_SECONDS
224-
+ "|tcpKeepAlive=true|dns=nonBlocking";
222+
+ "|tcpKeepAlive=true";
225223
}
226224

227225
// ========================================================================
@@ -295,16 +293,6 @@ private static S3AsyncClient buildS3AsyncClient(S3ClientConfig config, ResolvedA
295293
.connectionMaxIdleTime(Duration.ofSeconds(CONNECTION_MAX_IDLE_TIME_SECONDS))
296294
.tcpKeepAlive(true);
297295

298-
if (isNonBlockingDnsResolverAvailable())
299-
{
300-
httpClientBuilder.useNonBlockingDnsResolver(true);
301-
}
302-
else
303-
{
304-
LOGGER.info("Netty non-blocking DNS resolver is not available on the classpath; "
305-
+ "building S3AsyncClient with the AWS SDK default DNS resolver");
306-
}
307-
308296
software.amazon.awssdk.services.s3.S3AsyncClientBuilder builder = S3AsyncClient.builder()
309297
.region(Region.of(config.s3Region()))
310298
.credentialsProvider(credentialsProvider)
@@ -317,35 +305,16 @@ private static S3AsyncClient buildS3AsyncClient(S3ClientConfig config, ResolvedA
317305
}
318306

319307
LOGGER.info("Built S3AsyncClient region={} maxConcurrency={} maxPendingConnectionAcquires={} "
320-
+ "nonBlockingDnsResolver={} (knob={}, taskSlotsSource={}, taskSlots={})",
308+
+ "(knob={}, taskSlotsSource={}, taskSlots={})",
321309
config.s3Region(),
322310
resolved.maxConcurrency,
323311
resolved.maxPendingConnectionAcquires,
324-
isNonBlockingDnsResolverAvailable(),
325312
config.s3HttpMaxConcurrency(),
326313
resolved.taskSlots.source,
327314
resolved.taskSlots.taskSlots);
328315
return builder.build();
329316
}
330317

331-
static boolean isNonBlockingDnsResolverAvailable()
332-
{
333-
return NON_BLOCKING_DNS_RESOLVER_AVAILABLE;
334-
}
335-
336-
private static boolean isClassAvailable(String className)
337-
{
338-
try
339-
{
340-
Class.forName(className, false, S3ClientCache.class.getClassLoader());
341-
return true;
342-
}
343-
catch (ClassNotFoundException exception)
344-
{
345-
return false;
346-
}
347-
}
348-
349318
static int resolveMaxConcurrency(S3ClientConfig config)
350319
{
351320
int maxConcurrency = config.s3HttpMaxConcurrency();

cassandra-analytics-core/src/test/java/org/apache/cassandra/spark/data/S3ClientCacheTest.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -223,13 +223,6 @@ void testResolveMaxPendingConnectionAcquires()
223223
assertThat(S3ClientCache.resolveMaxPendingConnectionAcquires(2000)).isEqualTo(2048);
224224
}
225225

226-
@Test
227-
void testNonBlockingDnsResolverAvailabilityMatchesClasspath()
228-
{
229-
assertThat(S3ClientCache.isNonBlockingDnsResolverAvailable())
230-
.isEqualTo(isClassAvailable(S3ClientCache.NETTY_DNS_RESOLVER_CLASS));
231-
}
232-
233226
@Test
234227
void testResolveTaskSlotsPrioritizesSparkConfThenEnvThenRuntime()
235228
{
@@ -395,17 +388,4 @@ private S3ClientConfig createConfig(Map<String, String> options)
395388
{
396389
return S3ClientConfig.create(new CaseInsensitiveStringMap(options));
397390
}
398-
399-
private static boolean isClassAvailable(String className)
400-
{
401-
try
402-
{
403-
Class.forName(className, false, S3ClientCacheTest.class.getClassLoader());
404-
return true;
405-
}
406-
catch (ClassNotFoundException exception)
407-
{
408-
return false;
409-
}
410-
}
411391
}

0 commit comments

Comments
 (0)