-
Notifications
You must be signed in to change notification settings - Fork 631
Support intra-broker throttling (replica.alter.log.dirs.io.max.bytes.per.second) #2145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
79d77c0
a6db859
6879b58
e5f6489
a6c27cc
69a82c0
bea9d53
6b168bf
76ca5f7
411fbbe
685865d
fda2ab0
02057a3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -650,7 +650,11 @@ private static boolean hasProposalsToExecute(Collection<ExecutionProposal> propo | |
* @param replicaMovementStrategy The strategy used to determine the execution order of generated replica movement tasks | ||
* (if null, use default.replica.movement.strategies). | ||
* @param replicationThrottle The replication throttle (bytes/second) to apply to both leaders and followers | ||
* when executing proposals (if null, no throttling is applied). | ||
* when executing proposals; That is, this parameter only affects inter-broker replica | ||
* movements (if null, no throttling is applied). | ||
* @param logDirThrottle The throttle (bytes/second) to apply to replicas being moved between the log dirs | ||
* when executing proposals; That is, this parameter only affects intra-broker replica | ||
* movements (if null, no throttling is applied). | ||
* @param isTriggeredByUserRequest Whether the execution is triggered by a user request. | ||
* @param uuid UUID of the execution. | ||
* @param skipInterBrokerReplicaConcurrencyAdjustment {@code true} to skip auto adjusting concurrency of inter-broker | ||
|
@@ -667,14 +671,15 @@ public void executeProposals(Set<ExecutionProposal> proposals, | |
Long executionProgressCheckIntervalMs, | ||
ReplicaMovementStrategy replicaMovementStrategy, | ||
Long replicationThrottle, | ||
Long logDirThrottle, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not add |
||
boolean isTriggeredByUserRequest, | ||
String uuid, | ||
boolean skipInterBrokerReplicaConcurrencyAdjustment) throws OngoingExecutionException { | ||
if (hasProposalsToExecute(proposals, uuid)) { | ||
_executor.executeProposals(proposals, unthrottledBrokers, null, _loadMonitor, concurrentInterBrokerPartitionMovements, | ||
maxInterBrokerPartitionMovements, concurrentIntraBrokerPartitionMovements, clusterConcurrentLeaderMovements, | ||
brokerConcurrentLeaderMovements, executionProgressCheckIntervalMs, replicaMovementStrategy, replicationThrottle, | ||
isTriggeredByUserRequest, uuid, isKafkaAssignerMode, skipInterBrokerReplicaConcurrencyAdjustment); | ||
logDirThrottle, isTriggeredByUserRequest, uuid, isKafkaAssignerMode, skipInterBrokerReplicaConcurrencyAdjustment); | ||
} else { | ||
failGeneratingProposalsForExecution(uuid); | ||
} | ||
|
@@ -720,7 +725,7 @@ public void executeRemoval(Set<ExecutionProposal> proposals, | |
_executor.executeProposals(proposals, throttleDecommissionedBroker ? Collections.emptySet() : removedBrokers, removedBrokers, | ||
_loadMonitor, concurrentInterBrokerPartitionMovements, maxInterBrokerPartitionMovements, 0, | ||
clusterLeaderMovementConcurrency, brokerLeaderMovementConcurrency, | ||
executionProgressCheckIntervalMs, replicaMovementStrategy, replicationThrottle, | ||
executionProgressCheckIntervalMs, replicaMovementStrategy, replicationThrottle, null, | ||
isTriggeredByUserRequest, uuid, isKafkaAssignerMode, false); | ||
} else { | ||
failGeneratingProposalsForExecution(uuid); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
import com.codahale.metrics.Gauge; | ||
import com.codahale.metrics.MetricRegistry; | ||
import com.codahale.metrics.Timer; | ||
import com.google.common.collect.Sets; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we use new HashSet<>() from java.util here instead? |
||
import com.google.common.util.concurrent.AtomicDouble; | ||
import com.linkedin.kafka.cruisecontrol.KafkaCruiseControlUtils; | ||
import com.linkedin.kafka.cruisecontrol.common.TopicMinIsrCache; | ||
|
@@ -801,6 +802,8 @@ public boolean setConcurrencyAdjusterMinIsrCheck(boolean isMinIsrBasedConcurrenc | |
* @param replicaMovementStrategy The strategy used to determine the execution order of generated replica movement tasks. | ||
* @param replicationThrottle The replication throttle (bytes/second) to apply to both leaders and followers | ||
* when executing a proposal (if null, no throttling is applied). | ||
* @param logDirThrottle The throttle (bytes/second) to apply to replicas being moved between the log dirs | ||
* when executing a proposal (if null, no throttling is applied). | ||
* @param isTriggeredByUserRequest Whether the execution is triggered by a user request. | ||
* @param uuid UUID of the execution. | ||
* @param isKafkaAssignerMode {@code true} if kafka assigner mode, {@code false} otherwise. | ||
|
@@ -819,6 +822,7 @@ public synchronized void executeProposals(Collection<ExecutionProposal> proposal | |
Long requestedExecutionProgressCheckIntervalMs, | ||
ReplicaMovementStrategy replicaMovementStrategy, | ||
Long replicationThrottle, | ||
Long logDirThrottle, | ||
boolean isTriggeredByUserRequest, | ||
String uuid, | ||
boolean isKafkaAssignerMode, | ||
|
@@ -831,7 +835,7 @@ public synchronized void executeProposals(Collection<ExecutionProposal> proposal | |
requestedIntraBrokerPartitionMovementConcurrency, requestedClusterLeadershipMovementConcurrency, | ||
requestedBrokerLeadershipMovementConcurrency, requestedExecutionProgressCheckIntervalMs, replicaMovementStrategy, | ||
isTriggeredByUserRequest, loadMonitor); | ||
startExecution(loadMonitor, null, removedBrokers, replicationThrottle, isTriggeredByUserRequest); | ||
startExecution(loadMonitor, null, removedBrokers, replicationThrottle, logDirThrottle, isTriggeredByUserRequest); | ||
CCisGG marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} catch (Exception e) { | ||
if (e instanceof OngoingExecutionException) { | ||
LOG.info("User task {}: Broker removal operation aborted due to ongoing execution", uuid); | ||
|
@@ -924,7 +928,7 @@ public synchronized void executeDemoteProposals(Collection<ExecutionProposal> pr | |
initProposalExecution(proposals, demotedBrokers, concurrentSwaps, null, 0, | ||
requestedClusterLeadershipMovementConcurrency, requestedBrokerLeadershipMovementConcurrency, | ||
requestedExecutionProgressCheckIntervalMs, replicaMovementStrategy, isTriggeredByUserRequest, loadMonitor); | ||
startExecution(loadMonitor, demotedBrokers, null, replicationThrottle, isTriggeredByUserRequest); | ||
startExecution(loadMonitor, demotedBrokers, null, replicationThrottle, null, isTriggeredByUserRequest); | ||
} catch (Exception e) { | ||
processExecuteProposalsFailure(); | ||
throw e; | ||
|
@@ -1005,12 +1009,15 @@ private int numExecutionStartedInNonKafkaAssignerMode() { | |
* @param removedBrokers Brokers to be removed, null if no broker has been removed. | ||
* @param replicationThrottle The replication throttle (bytes/second) to apply to both leaders and followers | ||
* while moving partitions (if null, no throttling is applied). | ||
* @param logDirThrottle The throttle (bytes/second) to apply to replicas being moved between the log dirs | ||
* while moving partitions (if null, no throttling is applied). | ||
* @param isTriggeredByUserRequest Whether the execution is triggered by a user request. | ||
*/ | ||
private void startExecution(LoadMonitor loadMonitor, | ||
Collection<Integer> demotedBrokers, | ||
Collection<Integer> removedBrokers, | ||
Long replicationThrottle, | ||
Long logDirThrottle, | ||
boolean isTriggeredByUserRequest) throws OngoingExecutionException { | ||
_executionStoppedByUser.set(false); | ||
sanityCheckOngoingMovement(); | ||
|
@@ -1046,7 +1053,7 @@ private void startExecution(LoadMonitor loadMonitor, | |
_numExecutionStartedInNonKafkaAssignerMode.incrementAndGet(); | ||
} | ||
_proposalExecutor.execute( | ||
new ProposalExecutionRunnable(loadMonitor, demotedBrokers, removedBrokers, replicationThrottle, isTriggeredByUserRequest)); | ||
new ProposalExecutionRunnable(loadMonitor, demotedBrokers, removedBrokers, replicationThrottle, logDirThrottle, isTriggeredByUserRequest)); | ||
} | ||
|
||
/** | ||
|
@@ -1300,6 +1307,7 @@ private class ProposalExecutionRunnable implements Runnable { | |
private final Set<Integer> _recentlyDemotedBrokers; | ||
private final Set<Integer> _recentlyRemovedBrokers; | ||
private final Long _replicationThrottle; | ||
private final Long _logDirThrottle; | ||
private Throwable _executionException; | ||
private final boolean _isTriggeredByUserRequest; | ||
private long _lastSlowTaskReportingTimeMs; | ||
|
@@ -1314,6 +1322,7 @@ private class ProposalExecutionRunnable implements Runnable { | |
Collection<Integer> demotedBrokers, | ||
Collection<Integer> removedBrokers, | ||
Long replicationThrottle, | ||
Long logDirThrottle, | ||
boolean isTriggeredByUserRequest) { | ||
_loadMonitor = loadMonitor; | ||
_demotedBrokers = demotedBrokers; | ||
|
@@ -1349,6 +1358,7 @@ private class ProposalExecutionRunnable implements Runnable { | |
_recentlyDemotedBrokers = recentlyDemotedBrokers(); | ||
_recentlyRemovedBrokers = recentlyRemovedBrokers(); | ||
_replicationThrottle = replicationThrottle; | ||
_logDirThrottle = logDirThrottle; | ||
_isTriggeredByUserRequest = isTriggeredByUserRequest; | ||
_lastSlowTaskReportingTimeMs = -1L; | ||
if (_removedBrokers != null && !_removedBrokers.isEmpty()) { | ||
|
@@ -1606,8 +1616,7 @@ private void updateOngoingExecutionState() { | |
|
||
private void interBrokerMoveReplicas() throws InterruptedException, ExecutionException, TimeoutException { | ||
Set<Integer> currentDeadBrokersWithReplicas = _loadMonitor.deadBrokersWithReplicas(MAX_METADATA_WAIT_MS); | ||
ReplicationThrottleHelper throttleHelper = new ReplicationThrottleHelper(_adminClient, _replicationThrottle, | ||
currentDeadBrokersWithReplicas); | ||
ReplicationThrottleHelper throttleHelper = new ReplicationThrottleHelper(_adminClient, currentDeadBrokersWithReplicas); | ||
int numTotalPartitionMovements = _executionTaskManager.numRemainingInterBrokerPartitionMovements(); | ||
long totalDataToMoveInMB = _executionTaskManager.remainingInterBrokerDataToMoveInMB(); | ||
long startTime = System.currentTimeMillis(); | ||
|
@@ -1622,7 +1631,10 @@ private void interBrokerMoveReplicas() throws InterruptedException, ExecutionExc | |
|
||
AlterPartitionReassignmentsResult result = null; | ||
if (!tasksToExecute.isEmpty()) { | ||
throttleHelper.setThrottles(tasksToExecute.stream().map(ExecutionTask::proposal).collect(Collectors.toList())); | ||
if (_replicationThrottle != null) { | ||
throttleHelper.setReplicationThrottles(tasksToExecute.stream().map(ExecutionTask::proposal).collect(Collectors.toList()), | ||
_replicationThrottle); | ||
} | ||
// Execute the tasks. | ||
_executionTaskManager.markTasksInProgress(tasksToExecute); | ||
result = ExecutionUtils.submitReplicaReassignmentTasks(_adminClient, tasksToExecute); | ||
|
@@ -1645,7 +1657,9 @@ private void interBrokerMoveReplicas() throws InterruptedException, ExecutionExc | |
.collect(Collectors.toList()); | ||
inProgressTasks.addAll(inExecutionTasks()); | ||
|
||
throttleHelper.clearThrottles(completedTasks, inProgressTasks); | ||
if (_replicationThrottle != null) { | ||
throttleHelper.clearInterBrokerThrottles(completedTasks, inProgressTasks); | ||
} | ||
} | ||
|
||
// Currently, _executionProgressCheckIntervalMs is only runtime adjusted for inter broker move tasks, not | ||
|
@@ -1676,20 +1690,28 @@ private void interBrokerMoveReplicas() throws InterruptedException, ExecutionExc | |
} | ||
} | ||
|
||
private void intraBrokerMoveReplicas() { | ||
private void intraBrokerMoveReplicas() throws InterruptedException, ExecutionException, TimeoutException { | ||
ReplicationThrottleHelper throttleHelper = new ReplicationThrottleHelper(_adminClient); | ||
int numTotalPartitionMovements = _executionTaskManager.numRemainingIntraBrokerPartitionMovements(); | ||
long totalDataToMoveInMB = _executionTaskManager.remainingIntraBrokerDataToMoveInMB(); | ||
long startTime = System.currentTimeMillis(); | ||
LOG.info("User task {}: Starting {} intra-broker partition movements.", _uuid, numTotalPartitionMovements); | ||
|
||
int partitionsToMove = numTotalPartitionMovements; | ||
Set<Integer> participatingBrokers = Sets.newHashSet(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we use It appears that |
||
// Exhaust all the pending partition movements. | ||
while ((partitionsToMove > 0 || !inExecutionTasks().isEmpty()) && _stopSignal.get() == NO_STOP_EXECUTION) { | ||
// Get tasks to execute. | ||
List<ExecutionTask> tasksToExecute = _executionTaskManager.getIntraBrokerReplicaMovementTasks(); | ||
LOG.info("User task {}: Executor will execute {} task(s)", _uuid, tasksToExecute.size()); | ||
|
||
if (!tasksToExecute.isEmpty()) { | ||
if (_logDirThrottle != null) { | ||
participatingBrokers = throttleHelper.setLogDirThrottles( | ||
tasksToExecute.stream().map(ExecutionTask::proposal).collect(Collectors.toList()), | ||
_logDirThrottle | ||
); | ||
} | ||
// Execute the tasks. | ||
_executionTaskManager.markTasksInProgress(tasksToExecute); | ||
executeIntraBrokerReplicaMovements(tasksToExecute, _adminClient, _executionTaskManager, _config); | ||
|
@@ -1715,6 +1737,11 @@ private void intraBrokerMoveReplicas() { | |
waitForIntraBrokerReplicaTasksToFinish(); | ||
inExecutionTasks = inExecutionTasks(); | ||
} | ||
|
||
if (_logDirThrottle != null) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for my understanding, why the underscore in the variable names here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In consistency with |
||
throttleHelper.clearIntraBrokerThrottles(participatingBrokers); | ||
} | ||
|
||
if (inExecutionTasks().isEmpty()) { | ||
LOG.info("User task {}: Intra-broker partition movements finished.", _uuid); | ||
} else if (_stopSignal.get() != NO_STOP_EXECUTION) { | ||
|
Uh oh!
There was an error while loading. Please reload this page.