Skip to content

Commit 4dc9630

Browse files
committed
Merge branch 'master' into server-view-improvements-historical
2 parents ac8c380 + 516e3af commit 4dc9630

88 files changed

Lines changed: 2772 additions & 1937 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/configuration/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,7 @@ Middle Managers pass their configurations down to their child peons. The Middle
13621362
|`druid.worker.baseTaskDirs`|List of base temporary working directories, one of which is assigned per task in a round-robin fashion. This property can be used to allow usage of multiple disks for indexing. This property is recommended in place of and takes precedence over `${druid.indexer.task.baseTaskDir}`. If this configuration is not set, `${druid.indexer.task.baseTaskDir}` is used. For example, `druid.worker.baseTaskDirs=[\"PATH1\",\"PATH2\",...]`.|null|
13631363
|`druid.worker.baseTaskDirSize`|The total amount of bytes that can be used by tasks on any single task dir. This value is treated symmetrically across all directories, that is, if this is 500 GB and there are 3 `baseTaskDirs`, then each of those task directories is assumed to allow for 500 GB to be used and a total of 1.5 TB will potentially be available across all tasks. The actual amount of memory assigned to each task is discussed in [Configuring task storage sizes](../ingestion/tasks.md#configuring-task-storage-sizes)|`Long.MAX_VALUE`|
13641364
|`druid.worker.category`|A string to name the category that the Middle Manager node belongs to.|`_default_worker_category`|
1365+
|`druid.worker.startAlwaysEnabled`|If true, the Middle Manager always starts in the enabled state. If false, a disabled state set via the worker disable API is persisted and restored across restarts.|`false`|
13651366
|`druid.indexer.fork.property.druid.centralizedDatasourceSchema.enabled`| This config should be set when [Centralized Datasource Schema](#centralized-datasource-schema-experimental) feature is enabled. |false|
13661367

13671368
#### Peon processing
@@ -1478,6 +1479,7 @@ For most types of tasks, `SegmentWriteOutMediumFactory` can be configured per-ta
14781479
|`druid.worker.baseTaskDirSize`|The total amount of bytes that can be used by tasks on any single task dir. This value is treated symmetrically across all directories, that is, if this is 500 GB and there are 3 `baseTaskDirs`, then each of those task directories is assumed to allow for 500 GB to be used and a total of 1.5 TB will potentially be available across all tasks. The actual amount of memory assigned to each task is discussed in [Configuring task storage sizes](../ingestion/tasks.md#configuring-task-storage-sizes)|`Long.MAX_VALUE`|
14791480
|`druid.worker.globalIngestionHeapLimitBytes`|Total amount of heap available for ingestion processing. This is applied by automatically setting the `maxBytesInMemory` property on tasks.|Configured max JVM heap size / 6|
14801481
|`druid.worker.numConcurrentMerges`|Maximum number of segment persist or merge operations that can run concurrently across all tasks.|`druid.worker.capacity` / 2, rounded down|
1482+
|`druid.worker.startAlwaysEnabled`|If true, the Indexer always starts in the enabled state. If false, a disabled state set via the worker disable API is persisted and restored across restarts.|`false`|
14811483
|`druid.indexer.task.baseDir`|Base temporary working directory.|`System.getProperty("java.io.tmpdir")`|
14821484
|`druid.indexer.task.baseTaskDir`|Base temporary working directory for tasks.|`${druid.indexer.task.baseDir}/persistent/tasks`|
14831485
|`druid.indexer.task.gracefulShutdownTimeout`|Wait this long on Indexer restart for restorable tasks to gracefully exit.|`PT5M`|

docs/development/extensions-core/druid-pac4j.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ druid.auth.authenticator.jwt.type=jwt
5555
|`druid.auth.pac4j.oidc.discoveryURI`|discovery URI for fetching OP metadata [see this](http://openid.net/specs/openid-connect-discovery-1_0.html).|none|Yes|
5656
|`druid.auth.pac4j.oidc.oidcClaim`|[claim](https://openid.net/specs/openid-connect-core-1_0.html#Claims) that will be extracted from the ID Token after validation.|name|No|
5757
|`druid.auth.pac4j.oidc.scope`| scope is used by an application during authentication to authorize access to a user's details.|`openid profile email`|No|
58+
|`druid.auth.pac4j.oidc.clientAuthenticationMethod`|The client authentication method to use when communicating with the OIDC provider. Supported values: `client_secret_basic`, `client_secret_post`, `client_secret_jwt`, `private_key_jwt`, `none`. If not specified, pac4j will auto-detect the method from the provider's discovery document. Set this explicitly if you need to use a specific method (e.g., when your provider advertises multiple methods but you want to use a particular one).|Auto-detected from provider|No|
5859

5960
:::info
6061
Users must set a strong passphrase to ensure that an attacker is not able to guess it simply by brute force.

docs/ingestion/supervisor.md

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -193,29 +193,30 @@ The following example shows a supervisor spec with `lagBased` autoscaler:
193193
```
194194
</details>
195195

196-
**2. Cost-based autoscaler strategy (experimental)**
196+
**2. Cost-based autoscaler strategy**
197197

198-
An autoscaler which computes the required supervisor task count via cost function based on ingestion lag and poll-to-idle ratio.
199-
Task counts are selected from a bounded range derived from the current partitions-per-task ratio,
200-
not strictly from factors/divisors of the partition count. This bounded partitions-per-task window enables gradual scaling while
201-
voiding large jumps and still allowing non-divisor task counts when needed.
198+
The cost-based autoscaler picks the number of ingestion tasks that minimizes a combined cost score. The score has two components:
202199

203-
**It is experimental and the implementation details as well as cost function parameters are subject to change.**
200+
- **Lag cost** — how long it would take to drain the current backlog at the observed processing rate. More tasks reduce this cost.
201+
- **Idle cost** — how far the predicted idle ratio is from the target of ~25%. Tasks that are too busy (under-provisioned) or too idle (over-provisioned) both drive the score up.
202+
The sweet spot is roughly 25% idle, giving headroom to absorb traffic spikes without wasting resources.
203+
204+
At every evaluation interval, Druid computes the score for each candidate task count and picks the one with the lowest total cost.
204205

205206
Note: Kinesis is not supported yet, support is in progress.
206207

207208
The following table outlines the configuration properties related to the `costBased` autoscaler strategy:
208209

209-
| Property|Description|Required|Default|
210-
|---------|-----------|--------|-------|
211-
|`scaleActionPeriodMillis`|The frequency in milliseconds to check if a scale action is triggered. | No | 600000 |
212-
|`lagWeight`|The weight of extracted lag value in cost function.| No| 0.25 |
213-
|`idleWeight`|The weight of extracted poll idle value in cost function. | No | 0.75 |
214-
|`useTaskCountBoundaries`|Enables the bounded partitions-per-task window when selecting task counts.|No| `false` |
215-
|`highLagThreshold`|Average partition lag threshold that triggers burst scale-up when set to a value greater than `0`. Set to a negative value to disable burst scale-up.|No|-1|
216-
|`minScaleUpDelay`|Minimum cooldown duration after a scale-up action before the next scale-up is allowed, specified as an ISO-8601 duration string.|No||
217-
|`minScaleDownDelay`|Minimum cooldown duration after a scale-down action before the next scale-down is allowed, specified as an ISO-8601 duration string.|No|`PT30M`|
218-
|`scaleDownDuringTaskRolloverOnly`|Indicates whether task scaling down is limited to periods during task rollovers only.|No|`false`|
210+
| Property | Description | Required | Default |
211+
|----------|-------------|----------|---------------------------|
212+
|`scaleActionPeriodMillis`|How often, in milliseconds, Druid evaluates whether to scale.|No| `600000` (10 min) |
213+
|`lagWeight`|How much weight to give the lag cost relative to the idle cost. Higher values make the autoscaler more aggressive about adding tasks to drain backlog.|No| `0.4` |
214+
|`idleWeight`|How much weight to give the idle cost relative to the lag cost. Higher values make the autoscaler more aggressive about removing over-provisioned tasks.|No| `0.6` |
215+
|`useTaskCountBoundariesOnScaleUp`|Limits scale-up to a small step relative to the current task count, preventing large jumps. Disable to allow the autoscaler to jump directly to any task count.|No| `false` |
216+
|`useTaskCountBoundariesOnScaleDown`|Limits scale-down to a small step relative to the current task count, preventing large drops. Disable to allow the autoscaler to drop directly to any task count.|No| `true` |
217+
|`minScaleUpDelay`|Minimum cooldown after a scale-up before the next scale-up is allowed. Specified as an ISO-8601 duration.|No| `scaleActionPeriodMillis` |
218+
|`minScaleDownDelay`|Minimum cooldown after a scale-down before the next scale-down is allowed. Specified as an ISO-8601 duration.|No| `PT30M` |
219+
|`scaleDownDuringTaskRolloverOnly`|If `true`, scale-down actions are deferred until the next task rollover. This avoids disrupting in-progress ingestion.|No| `false` |
219220

220221
The following example shows a supervisor spec with `costBased` autoscaler:
221222

@@ -231,10 +232,10 @@ The following example shows a supervisor spec with `costBased` autoscaler:
231232
"autoScalerStrategy": "costBased",
232233
"taskCountMin": 1,
233234
"taskCountMax": 10,
235+
"lagWeight": 0.4,
236+
"idleWeight": 0.6,
234237
"minScaleUpDelay": "PT10M",
235-
"minScaleDownDelay": "PT30M",
236-
"lagWeight": 0.1,
237-
"idleWeight": 0.9
238+
"minScaleDownDelay": "PT30M"
238239
}
239240
}
240241
}

embedded-tests/src/test/java/org/apache/druid/testing/embedded/indexing/autoscaler/CostBasedAutoScalerIntegrationTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ public void test_autoScaler_computesOptimalTaskCountAndProducesScaleUp()
143143
}
144144
});
145145

146-
// These values were carefully handpicked to allow that test to pass in a stable manner.
146+
// These values were carefully handpicked to allow that test to pass stably.
147147
final CostBasedAutoScalerConfig autoScalerConfig = CostBasedAutoScalerConfig
148148
.builder()
149149
.enableTaskAutoScaler(true)
@@ -152,8 +152,8 @@ public void test_autoScaler_computesOptimalTaskCountAndProducesScaleUp()
152152
.taskCountStart(lowInitialTaskCount)
153153
.scaleActionPeriodMillis(500)
154154
.minTriggerScaleActionFrequencyMillis(1000)
155-
.lagWeight(0.2)
156-
.idleWeight(0.8)
155+
.lagWeight(0.8)
156+
.idleWeight(0.2)
157157
.build();
158158

159159
final KafkaSupervisorSpec kafkaSupervisorSpec = createKafkaSupervisorWithAutoScaler(
@@ -192,11 +192,11 @@ public void test_autoScaler_scalesUpAndDown_withSlowPublish()
192192

193193
final CostBasedAutoScalerConfig autoScalerConfig = CostBasedAutoScalerConfig
194194
.builder()
195+
.enableTaskAutoScaler(true)
195196
.taskCountMin(1)
196197
.taskCountMax(4)
197-
.lagWeight(1.0)
198-
.idleWeight(1.0)
199-
.enableTaskAutoScaler(true)
198+
.lagWeight(0.5)
199+
.idleWeight(0.5)
200200
.minTriggerScaleActionFrequencyMillis(10L)
201201
.scaleActionPeriodMillis(10L)
202202
.minScaleDownDelay(Duration.standardSeconds(1))

extensions-core/druid-catalog/src/main/java/org/apache/druid/catalog/sync/CacheNotifier.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public void start()
8787
return;
8888
}
8989
catch (Throwable t) {
90-
LOG.makeAlert(t, callerName + ": Error occured while handling updates.").emit();
90+
LOG.makeAlert(t, callerName + ": Error occurred while handling updates.").emit();
9191
}
9292
}
9393
});

extensions-core/druid-catalog/src/main/java/org/apache/druid/catalog/sync/CatalogUpdateReceiver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public void start()
8585
LOG.debug("Scheduled catalog refresh is done");
8686
}
8787
catch (Throwable t) {
88-
LOG.makeAlert(t, "Error occured while refreshing catalog.").emit();
88+
LOG.makeAlert(t, "Error occurred while refreshing catalog.").emit();
8989
}
9090
}
9191
);

extensions-core/druid-pac4j/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@
3434
</parent>
3535

3636
<properties>
37-
<pac4j.version>5.7.3</pac4j.version>
37+
<pac4j.version>5.7.10</pac4j.version>
3838

3939
<!-- Following must be updated along with any updates to pac4j version. One can find the compatible version of nimbus libraries in org.pac4j:pac4j-oidc dependencies-->
4040
<nimbus.lang.tag.version>1.7</nimbus.lang.tag.version>
41-
<nimbus.jose.jwt.version>9.37.2</nimbus.jose.jwt.version>
41+
<nimbus.jose.jwt.version>9.37.3</nimbus.jose.jwt.version>
4242
<oauth2.oidc.sdk.version>10.8</oauth2.oidc.sdk.version>
4343
</properties>
4444

extensions-core/druid-pac4j/src/main/java/org/apache/druid/security/pac4j/OIDCConfig.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,25 @@ public class OIDCConfig
4444
@JsonProperty
4545
private final String scope;
4646

47+
@JsonProperty
48+
private final String clientAuthenticationMethod;
49+
4750
@JsonCreator
4851
public OIDCConfig(
4952
@JsonProperty("clientID") String clientID,
5053
@JsonProperty("clientSecret") PasswordProvider clientSecret,
5154
@JsonProperty("discoveryURI") String discoveryURI,
5255
@JsonProperty("oidcClaim") String oidcClaim,
53-
@JsonProperty("scope") @Nullable String scope
56+
@JsonProperty("scope") @Nullable String scope,
57+
@JsonProperty("clientAuthenticationMethod") @Nullable String clientAuthenticationMethod
5458
)
5559
{
5660
this.clientID = Preconditions.checkNotNull(clientID, "null clientID");
5761
this.clientSecret = Preconditions.checkNotNull(clientSecret, "null clientSecret");
5862
this.discoveryURI = Preconditions.checkNotNull(discoveryURI, "null discoveryURI");
5963
this.oidcClaim = oidcClaim == null ? DEFAULT_SCOPE : oidcClaim;
6064
this.scope = scope;
65+
this.clientAuthenticationMethod = clientAuthenticationMethod;
6166
}
6267

6368
@JsonProperty
@@ -89,4 +94,10 @@ public String getScope()
8994
{
9095
return scope;
9196
}
97+
98+
@JsonProperty
99+
public String getClientAuthenticationMethod()
100+
{
101+
return clientAuthenticationMethod;
102+
}
92103
}

extensions-core/druid-pac4j/src/main/java/org/apache/druid/security/pac4j/Pac4jAuthenticator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.google.common.base.Suppliers;
2828
import com.google.common.primitives.Ints;
2929
import com.google.inject.Provider;
30+
import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
3031
import com.nimbusds.oauth2.sdk.http.HTTPRequest;
3132
import org.apache.druid.server.security.AuthenticationResult;
3233
import org.apache.druid.server.security.Authenticator;
@@ -132,6 +133,10 @@ private Config createPac4jConfig(OIDCConfig oidcConfig)
132133
oidcConf.setSecret(oidcConfig.getClientSecret().getPassword());
133134
oidcConf.setDiscoveryURI(oidcConfig.getDiscoveryURI());
134135
oidcConf.setScope(oidcConfig.getScope());
136+
if (oidcConfig.getClientAuthenticationMethod() != null) {
137+
oidcConf.setClientAuthenticationMethod(
138+
ClientAuthenticationMethod.parse(oidcConfig.getClientAuthenticationMethod()));
139+
}
135140
oidcConf.setExpireSessionWithToken(true);
136141
oidcConf.setUseNonce(true);
137142
oidcConf.setReadTimeout(Ints.checkedCast(pac4jCommonConfig.getReadTimeout().getMillis()));

extensions-core/druid-pac4j/src/test/java/org/apache/druid/security/pac4j/OIDCConfigTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public void testSerde() throws Exception
4646
Assert.assertEquals("testdiscoveryuri", conf.getDiscoveryURI());
4747
Assert.assertEquals("name", conf.getOidcClaim());
4848
Assert.assertEquals("testscope", conf.getScope());
49+
Assert.assertNull(conf.getClientAuthenticationMethod());
4950
}
5051

5152
@Test
@@ -72,4 +73,31 @@ public void testSerdeWithoutDefaults() throws Exception
7273
Assert.assertEquals("email", conf.getOidcClaim());
7374
Assert.assertEquals("testscope", conf.getScope());
7475
}
76+
77+
@Test
78+
public void testSerdeWithClientAuthenticationMethod() throws Exception
79+
{
80+
ObjectMapper jsonMapper = new ObjectMapper();
81+
82+
String jsonStr = "{\n"
83+
+ " \"clientID\": \"testid\",\n"
84+
+ " \"clientSecret\": \"testsecret\",\n"
85+
+ " \"discoveryURI\": \"testdiscoveryuri\",\n"
86+
+ " \"oidcClaim\": \"email\",\n"
87+
+ " \"scope\": \"testscope\",\n"
88+
+ " \"clientAuthenticationMethod\": \"client_secret_post\"\n"
89+
+ "}\n";
90+
91+
OIDCConfig conf = jsonMapper.readValue(
92+
jsonMapper.writeValueAsString(jsonMapper.readValue(jsonStr, OIDCConfig.class)),
93+
OIDCConfig.class
94+
);
95+
96+
Assert.assertEquals("testid", conf.getClientID());
97+
Assert.assertEquals("testsecret", conf.getClientSecret().getPassword());
98+
Assert.assertEquals("testdiscoveryuri", conf.getDiscoveryURI());
99+
Assert.assertEquals("email", conf.getOidcClaim());
100+
Assert.assertEquals("testscope", conf.getScope());
101+
Assert.assertEquals("client_secret_post", conf.getClientAuthenticationMethod());
102+
}
75103
}

0 commit comments

Comments
 (0)