gianm commented on code in PR #19892:
URL: https://github.com/apache/druid/pull/19892#discussion_r3725942155
##########
docs/development/extensions-core/s3.md:
##########
@@ -142,6 +144,61 @@ For example, to set the region to 'us-east-1' through
system properties:
|`druid.storage.sse.kms.keyId`|AWS KMS key ID. This is used only when
`druid.storage.sse.type` is `kms` and can be empty to use the default key
ID.|None|
|`druid.storage.sse.custom.base64EncodedKey`|Base64-encoded key. Should be
specified if `druid.storage.sse.type` is `custom`.|None|
+## Retry behavior
+
+Druid names the AWS SDK retry strategy explicitly rather than accepting the
SDK's default. The SDK's own default
+depends on the `aws.newRetries2026` migration flag, so leaving it unset would
let retry behavior change underneath
+Druid when that flag's default flips. For `standard` and `adaptive`, Druid
also opts in to the behavior AWS
+documents for those modes, rather than quietly falling back to any legacy
behavior the SDK may have.
+
+|Mode|Behavior|
+|----|--------|
+|`standard`|Error classification consistent with the other AWS SDK
implementations, and the mode AWS recommends for all workloads.|
+|`adaptive`|`standard` plus a client-side rate limiter that slows requests
down when S3 reports throttling. Unlike `standard`, it can delay or block the
**initial** request, not only retries. The limiter covers every request made by
one client instance, so throttling on one key prefix also slows requests to
prefixes that are not being throttled.|
+|`legacy`|The SDK's legacy behavior, retained so a deployment can revert
without a rollback. AWS recommends moving off it.|
+
+### Choosing a mode
Review Comment:
I don't think this section should be here. If we really think that these
suggestions are good then they should be implemented as defaults in code.
##########
cloud/aws-common/src/main/java/org/apache/druid/common/aws/AWSClientConfig.java:
##########
@@ -36,6 +44,68 @@ public class AWSClientConfig
/** AWS SDK v2's own default. */
private static final int DEFAULT_MAX_CONNECTIONS_FLOOR = 50;
+ /**
+ * Selects the retry behavior AWS documents for {@code standard} and {@code
adaptive} rather than the pre-2026
Review Comment:
I found this javadoc hard to understand until reading
https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html. It
would be helpful to reword the javadoc, or link to
https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html, or
ideally.
I think it would also be fine to get rid of this constant and instead inline
`true` into the calls to `standardRetryStrategy` and `adaptiveRetryStrategy`.
Sometimes less is more.
##########
docs/development/extensions-core/s3.md:
##########
@@ -142,6 +144,61 @@ For example, to set the region to 'us-east-1' through
system properties:
|`druid.storage.sse.kms.keyId`|AWS KMS key ID. This is used only when
`druid.storage.sse.type` is `kms` and can be empty to use the default key
ID.|None|
|`druid.storage.sse.custom.base64EncodedKey`|Base64-encoded key. Should be
specified if `druid.storage.sse.type` is `custom`.|None|
+## Retry behavior
+
+Druid names the AWS SDK retry strategy explicitly rather than accepting the
SDK's default. The SDK's own default
+depends on the `aws.newRetries2026` migration flag, so leaving it unset would
let retry behavior change underneath
+Druid when that flag's default flips. For `standard` and `adaptive`, Druid
also opts in to the behavior AWS
+documents for those modes, rather than quietly falling back to any legacy
behavior the SDK may have.
+
+|Mode|Behavior|
+|----|--------|
+|`standard`|Error classification consistent with the other AWS SDK
implementations, and the mode AWS recommends for all workloads.|
+|`adaptive`|`standard` plus a client-side rate limiter that slows requests
down when S3 reports throttling. Unlike `standard`, it can delay or block the
**initial** request, not only retries. The limiter covers every request made by
one client instance, so throttling on one key prefix also slows requests to
prefixes that are not being throttled.|
+|`legacy`|The SDK's legacy behavior, retained so a deployment can revert
without a rollback. AWS recommends moving off it.|
+
+### Choosing a mode
+
+AWS recommends `standard` as the default and `adaptive` only for workloads
that are *single-resource,
+throttling-heavy, and latency-tolerant*. S3 applies its request-rate limits
per key prefix, so "single-resource"
+means a process that concentrates its requests on one prefix.
+
+That maps onto Druid roughly as follows. Because a peon runs one task, you can
select a mode per task type — through
+a Kubernetes pod template, or `druid.indexer.fork.property.druid.s3.retryMode`
in a task's context when using the
+MiddleManager task runner.
+
+|Process|Suggested mode|Reasoning|
+|-------|--------------|---------|
+|MSQ and compaction peons|`adaptive`|Segment output goes to one new version
prefix and shuffle output to one prefix per query, which is exactly the
concentration that provokes throttling. Batch work tolerates the added latency.|
+|Batch ingestion peons|`standard`, or `adaptive` if throttled|Same shape as
above at lower request rates.|
+|Historicals|`standard`|One client loads segments for every datasource the
process serves, so a rate limiter tripped by one prefix would slow loads for
unrelated ones. Segment loads can also sit on the query path.|
+|Brokers, Coordinator, Overlord|`standard`|Low request volume, and delaying an
initial request costs query latency for no benefit.|
+
+### Retry quota
+
+Every mode carries a retry quota: a token bucket, held per client instance and
never shared across processes, that
+stops retries once it is exhausted so the client fails fast instead of adding
load a struggling service cannot
+absorb. It only engages under sustained failure — roughly a 32% failure rate
for throttling errors — and is inert
+otherwise. Choosing between the modes does not change whether it is present.
+
+S3 reports throttling as `SlowDown` and `503`, which the SDK classifies as
throttling rather than transient errors.
+Those get a longer base backoff than transient failures, and they are what
`adaptive`'s rate limiter reacts to.
+
+### Retries are layered
+
+`druid.s3.maxRetryAttempts` applies per HTTP request. Druid retries again on
top of it, and the two multiply:
+
+|Layer|Scope of one attempt|Attempts|Backoff cap|
+|-----|--------------------|--------|-----------|
+|`druid.s3.maxRetryAttempts`|A single HTTP request, such as one
`UploadPart`|Set by the retry mode|`~20s`|
+|`S3Utils.retryS3Operation`|A whole logical operation, such as re-uploading an
entire segment|10|`60s`|
Review Comment:
Operator docs shouldn't refer to Java classes/functions such as
`S3Utils.retryS3Operation`.
##########
docs/development/extensions-core/s3.md:
##########
@@ -142,6 +144,61 @@ For example, to set the region to 'us-east-1' through
system properties:
|`druid.storage.sse.kms.keyId`|AWS KMS key ID. This is used only when
`druid.storage.sse.type` is `kms` and can be empty to use the default key
ID.|None|
|`druid.storage.sse.custom.base64EncodedKey`|Base64-encoded key. Should be
specified if `druid.storage.sse.type` is `custom`.|None|
+## Retry behavior
+
+Druid names the AWS SDK retry strategy explicitly rather than accepting the
SDK's default. The SDK's own default
+depends on the `aws.newRetries2026` migration flag, so leaving it unset would
let retry behavior change underneath
+Druid when that flag's default flips. For `standard` and `adaptive`, Druid
also opts in to the behavior AWS
+documents for those modes, rather than quietly falling back to any legacy
behavior the SDK may have.
+
+|Mode|Behavior|
+|----|--------|
+|`standard`|Error classification consistent with the other AWS SDK
implementations, and the mode AWS recommends for all workloads.|
+|`adaptive`|`standard` plus a client-side rate limiter that slows requests
down when S3 reports throttling. Unlike `standard`, it can delay or block the
**initial** request, not only retries. The limiter covers every request made by
one client instance, so throttling on one key prefix also slows requests to
prefixes that are not being throttled.|
+|`legacy`|The SDK's legacy behavior, retained so a deployment can revert
without a rollback. AWS recommends moving off it.|
+
+### Choosing a mode
+
+AWS recommends `standard` as the default and `adaptive` only for workloads
that are *single-resource,
+throttling-heavy, and latency-tolerant*. S3 applies its request-rate limits
per key prefix, so "single-resource"
+means a process that concentrates its requests on one prefix.
+
+That maps onto Druid roughly as follows. Because a peon runs one task, you can
select a mode per task type — through
+a Kubernetes pod template, or `druid.indexer.fork.property.druid.s3.retryMode`
in a task's context when using the
+MiddleManager task runner.
+
+|Process|Suggested mode|Reasoning|
+|-------|--------------|---------|
+|MSQ and compaction peons|`adaptive`|Segment output goes to one new version
prefix and shuffle output to one prefix per query, which is exactly the
concentration that provokes throttling. Batch work tolerates the added latency.|
+|Batch ingestion peons|`standard`, or `adaptive` if throttled|Same shape as
above at lower request rates.|
+|Historicals|`standard`|One client loads segments for every datasource the
process serves, so a rate limiter tripped by one prefix would slow loads for
unrelated ones. Segment loads can also sit on the query path.|
+|Brokers, Coordinator, Overlord|`standard`|Low request volume, and delaying an
initial request costs query latency for no benefit.|
+
+### Retry quota
Review Comment:
Maybe better to link to
https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html vs
trying to summarize it.
##########
docs/development/extensions-core/s3.md:
##########
@@ -142,6 +144,61 @@ For example, to set the region to 'us-east-1' through
system properties:
|`druid.storage.sse.kms.keyId`|AWS KMS key ID. This is used only when
`druid.storage.sse.type` is `kms` and can be empty to use the default key
ID.|None|
|`druid.storage.sse.custom.base64EncodedKey`|Base64-encoded key. Should be
specified if `druid.storage.sse.type` is `custom`.|None|
+## Retry behavior
Review Comment:
Linking to
https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html
would be useful in this section.
##########
cloud/aws-common/src/main/java/org/apache/druid/common/aws/AWSClientConfig.java:
##########
@@ -80,6 +150,30 @@ public class AWSClientConfig
@Nullable
private Integer maxConnections = null;
+ /**
+ * Retry strategy applied to every AWS client built from this config.
+ * <p>
+ * Setting this at all is deliberate: left unset, the SDK picks its own
default, and which one it picks depends on
+ * the {@code aws.newRetries2026} migration flag. Naming the mode here keeps
retry behavior stable across SDK
+ * upgrades instead of changing under Druid when that flag's default flips.
+ */
+ @JsonProperty
+ private RetryMode retryMode = RetryMode.STANDARD;
+
+ /**
+ * Total attempts per request, including the first. Maps directly to the
SDK's {@code maxAttempts}, so 1 disables
Review Comment:
If 1 disables retries then this config should be named `maxAttempts`, not
`maxRetryAttempts`. (1 retry attempt means there were 2 attempts: an initial
attempt and a retry attempt).
##########
docs/development/extensions-core/s3.md:
##########
@@ -142,6 +144,61 @@ For example, to set the region to 'us-east-1' through
system properties:
|`druid.storage.sse.kms.keyId`|AWS KMS key ID. This is used only when
`druid.storage.sse.type` is `kms` and can be empty to use the default key
ID.|None|
|`druid.storage.sse.custom.base64EncodedKey`|Base64-encoded key. Should be
specified if `druid.storage.sse.type` is `custom`.|None|
+## Retry behavior
+
+Druid names the AWS SDK retry strategy explicitly rather than accepting the
SDK's default. The SDK's own default
+depends on the `aws.newRetries2026` migration flag, so leaving it unset would
let retry behavior change underneath
Review Comment:
I don't think mentioning this flag or the SDK defaults here is useful,
because neither of them matter (since we're explicitly creating policies such
that the flag and SDK defaults are ignored). Bringing them up makes it seem
like something the operator might need to care about.
##########
docs/development/extensions-core/s3.md:
##########
@@ -142,6 +144,61 @@ For example, to set the region to 'us-east-1' through
system properties:
|`druid.storage.sse.kms.keyId`|AWS KMS key ID. This is used only when
`druid.storage.sse.type` is `kms` and can be empty to use the default key
ID.|None|
|`druid.storage.sse.custom.base64EncodedKey`|Base64-encoded key. Should be
specified if `druid.storage.sse.type` is `custom`.|None|
+## Retry behavior
+
+Druid names the AWS SDK retry strategy explicitly rather than accepting the
SDK's default. The SDK's own default
+depends on the `aws.newRetries2026` migration flag, so leaving it unset would
let retry behavior change underneath
+Druid when that flag's default flips. For `standard` and `adaptive`, Druid
also opts in to the behavior AWS
+documents for those modes, rather than quietly falling back to any legacy
behavior the SDK may have.
+
+|Mode|Behavior|
+|----|--------|
+|`standard`|Error classification consistent with the other AWS SDK
implementations, and the mode AWS recommends for all workloads.|
+|`adaptive`|`standard` plus a client-side rate limiter that slows requests
down when S3 reports throttling. Unlike `standard`, it can delay or block the
**initial** request, not only retries. The limiter covers every request made by
one client instance, so throttling on one key prefix also slows requests to
prefixes that are not being throttled.|
+|`legacy`|The SDK's legacy behavior, retained so a deployment can revert
without a rollback. AWS recommends moving off it.|
+
+### Choosing a mode
+
+AWS recommends `standard` as the default and `adaptive` only for workloads
that are *single-resource,
+throttling-heavy, and latency-tolerant*. S3 applies its request-rate limits
per key prefix, so "single-resource"
+means a process that concentrates its requests on one prefix.
+
+That maps onto Druid roughly as follows. Because a peon runs one task, you can
select a mode per task type — through
+a Kubernetes pod template, or `druid.indexer.fork.property.druid.s3.retryMode`
in a task's context when using the
+MiddleManager task runner.
+
+|Process|Suggested mode|Reasoning|
Review Comment:
I'm not sure we can make such specific claims about how prefixes work with
rate limiting. The AWS docs, to me, seem vague as to what exactly the
rate-limitable prefix is. They don't appear to promise that it's any particular
prefix of the key. The page at
https://repost.aws/knowledge-center/s3-prefix-nested-folders-difference
suggests that AWS partitions the prefixes adaptively in some way that is
possibly opaque to the user.
Anyway, we won't need to worry about this if we remove the subsection as I
am also suggesting.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]