Search in sources :

Example 21 with ProvisionRecommendation

use of com.linkedin.kafka.cruisecontrol.analyzer.ProvisionRecommendation in project cruise-control by linkedin.

the class PartitionProvisionerTest method assertProvisionPartitionIncreaseConstructsCorrectResponse.

private void assertProvisionPartitionIncreaseConstructsCorrectResponse(KafkaCruiseControlUtils.CompletionType partitionIncreaseCompletion, ProvisionerState.State expectedState, String expectedSummary, boolean hasBrokerRecommendation) throws ExecutionException, InterruptedException, TimeoutException {
    int recommendedPartitionCount = expectedSummary.contains("Ignored") ? MOCK_IGNORED_PARTITION_COUNT : MOCK_PARTITION_COUNT;
    ProvisionRecommendation recommendation = new ProvisionRecommendation.Builder(ProvisionStatus.UNDER_PROVISIONED).numPartitions(recommendedPartitionCount).topicPattern(MOCK_TOPIC_PATTERN).build();
    Map<String, ProvisionRecommendation> provisionRecommendation;
    if (hasBrokerRecommendation) {
        provisionRecommendation = Map.of(RECOMMENDER_UP, recommendation, RECOMMENDER_TO_EXECUTE, BROKER_REC_TO_EXECUTE);
    } else {
        provisionRecommendation = Collections.singletonMap(RECOMMENDER_UP, recommendation);
    }
    Map<String, KafkaFuture<TopicDescription>> describeTopicsValues = Collections.singletonMap(MOCK_TOPIC, MOCK_TOPIC_DESCRIPTION_FUTURE);
    EasyMock.expect(MOCK_ADMIN_CLIENT.describeTopics(Collections.singletonList(MOCK_TOPIC))).andReturn(MOCK_DESCRIBE_TOPICS_RESULT);
    EasyMock.expect(MOCK_DESCRIBE_TOPICS_RESULT.values()).andReturn(describeTopicsValues);
    if (partitionIncreaseCompletion == COMPLETED) {
        EasyMock.expect(MOCK_TOPIC_DESCRIPTION_FUTURE.get(CLIENT_REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)).andReturn(MOCK_TOPIC_DESCRIPTION);
        // Create partitions: for this test, we ignore the fact that the mock cluster has one node -- i.e. in reality a request to increase
        // partition count to two would fail in a cluster with one node.
        EasyMock.expect(MOCK_ADMIN_CLIENT.createPartitions(Collections.singletonMap(MOCK_TOPIC, EasyMock.anyObject()))).andReturn(MOCK_CREATE_PARTITIONS_RESULT);
        Map<String, KafkaFuture<Void>> createPartitionsResultValues = Collections.singletonMap(MOCK_TOPIC, MOCK_CREATE_PARTITIONS_FUTURE);
        EasyMock.expect(MOCK_CREATE_PARTITIONS_RESULT.values()).andReturn(createPartitionsResultValues);
        EasyMock.expect(MOCK_CREATE_PARTITIONS_FUTURE.get(CLIENT_REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)).andReturn(null);
    } else if (partitionIncreaseCompletion == KafkaCruiseControlUtils.CompletionType.COMPLETED_WITH_ERROR) {
        EasyMock.expect(MOCK_TOPIC_DESCRIPTION_FUTURE.get(CLIENT_REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)).andThrow(new ExecutionException(new InvalidTopicException()));
    } else {
        EasyMock.expect(MOCK_TOPIC_DESCRIPTION_FUTURE.get(CLIENT_REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)).andReturn(MOCK_TOPIC_DESCRIPTION);
    }
    EasyMock.replay(MOCK_ADMIN_CLIENT, MOCK_DESCRIBE_TOPICS_RESULT, MOCK_TOPIC_DESCRIPTION_FUTURE, MOCK_CREATE_PARTITIONS_FUTURE, MOCK_CREATE_PARTITIONS_RESULT);
    ProvisionerState results = _provisioner.rightsize(provisionRecommendation, RIGHTSIZE_OPTIONS);
    assertEquals(expectedState, results.state());
    assertEquals(expectedSummary, results.summary());
}
Also used : ProvisionRecommendation(com.linkedin.kafka.cruisecontrol.analyzer.ProvisionRecommendation) KafkaFuture(org.apache.kafka.common.KafkaFuture) InvalidTopicException(org.apache.kafka.common.errors.InvalidTopicException) ExecutionException(java.util.concurrent.ExecutionException)

Example 22 with ProvisionRecommendation

use of com.linkedin.kafka.cruisecontrol.analyzer.ProvisionRecommendation in project cruise-control by linkedin.

the class ResourceDistributionGoal method initGoalState.

/**
 * (1) Initialize the current resource to be balanced or self healed.
 * (2) Set the flag which indicates whether the self healing failed to relocate all replicas away from dead brokers
 * in its initial attempt. Since self healing has not been executed yet, this flag is false.
 *
 * @param clusterModel The state of the cluster.
 * @param optimizationOptions Options to take into account during optimization.
 */
@Override
protected void initGoalState(ClusterModel clusterModel, OptimizationOptions optimizationOptions) throws OptimizationFailureException {
    _brokersAllowedReplicaMove = GoalUtils.aliveBrokersNotExcludedForReplicaMove(clusterModel, optimizationOptions);
    if (_brokersAllowedReplicaMove.isEmpty()) {
        // Handle the case when all alive brokers are excluded from replica moves.
        ProvisionRecommendation recommendation = new ProvisionRecommendation.Builder(ProvisionStatus.UNDER_PROVISIONED).numBrokers(clusterModel.maxReplicationFactor()).build();
        throw new OptimizationFailureException(String.format("[%s] All alive brokers are excluded from replica moves.", name()), recommendation);
    }
    _fixOfflineReplicasOnly = false;
    double resourceUtilization = clusterModel.load().expectedUtilizationFor(resource());
    double capacity = clusterModel.capacityWithAllowedReplicaMovesFor(resource(), optimizationOptions);
    // Cluster utilization excludes the capacity of brokers excluded for replica moves.
    double avgUtilizationPercentage = resourceUtilization / capacity;
    _balanceUpperThreshold = GoalUtils.computeResourceUtilizationBalanceThreshold(avgUtilizationPercentage, resource(), _balancingConstraint, optimizationOptions.isTriggeredByGoalViolation(), BALANCE_MARGIN, false);
    _balanceLowerThreshold = GoalUtils.computeResourceUtilizationBalanceThreshold(avgUtilizationPercentage, resource(), _balancingConstraint, optimizationOptions.isTriggeredByGoalViolation(), BALANCE_MARGIN, true);
    // Identify whether the cluster is in a low utilization state.
    _isLowUtilization = avgUtilizationPercentage <= _balancingConstraint.lowUtilizationThreshold(resource());
    if (_isLowUtilization) {
        // Identify a typical broker capacity to be used in recommendations in case the cluster is over-provisioned.
        // To make sure that the recommended brokers to drop in an heterogeneous cluster is a positive number, the typical broker must have
        // the max capacity.
        int typicalBrokerId = brokerIdWithMaxCapacity(clusterModel);
        double typicalCapacity = clusterModel.broker(typicalBrokerId).capacityFor(resource());
        // Any capacity greater than the allowed capacity may yield over-provisioning.
        double allowedCapacity = resourceUtilization / _balancingConstraint.lowUtilizationThreshold(resource());
        int allowedNumBrokers = (int) (allowedCapacity / typicalCapacity);
        int numBrokersToDrop = Math.max(_brokersAllowedReplicaMove.size() - allowedNumBrokers, 1);
        _overProvisionedRecommendation = new ProvisionRecommendation.Builder(ProvisionStatus.OVER_PROVISIONED).numBrokers(numBrokersToDrop).typicalBrokerCapacity(typicalCapacity).typicalBrokerId(typicalBrokerId).resource(resource()).build();
    }
}
Also used : ProvisionRecommendation(com.linkedin.kafka.cruisecontrol.analyzer.ProvisionRecommendation) OptimizationFailureException(com.linkedin.kafka.cruisecontrol.exception.OptimizationFailureException) BalancingConstraint(com.linkedin.kafka.cruisecontrol.analyzer.BalancingConstraint)

Aggregations

ProvisionRecommendation (com.linkedin.kafka.cruisecontrol.analyzer.ProvisionRecommendation)22 OptimizationFailureException (com.linkedin.kafka.cruisecontrol.exception.OptimizationFailureException)18 Broker (com.linkedin.kafka.cruisecontrol.model.Broker)11 BalancingConstraint (com.linkedin.kafka.cruisecontrol.analyzer.BalancingConstraint)8 Replica (com.linkedin.kafka.cruisecontrol.model.Replica)7 SortedReplicasHelper (com.linkedin.kafka.cruisecontrol.model.SortedReplicasHelper)7 HashSet (java.util.HashSet)4 ProvisionResponse (com.linkedin.kafka.cruisecontrol.analyzer.ProvisionResponse)3 Map (java.util.Map)3 Resource (com.linkedin.kafka.cruisecontrol.common.Resource)2 ActionAcceptance (com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance)1 ACCEPT (com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance.ACCEPT)1 BROKER_REJECT (com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance.BROKER_REJECT)1 REPLICA_REJECT (com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance.REPLICA_REJECT)1 ActionType (com.linkedin.kafka.cruisecontrol.analyzer.ActionType)1 BalancingAction (com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction)1 OptimizationOptions (com.linkedin.kafka.cruisecontrol.analyzer.OptimizationOptions)1 ProvisionStatus (com.linkedin.kafka.cruisecontrol.analyzer.ProvisionStatus)1 MIN_NUM_VALID_WINDOWS_FOR_SELF_HEALING (com.linkedin.kafka.cruisecontrol.analyzer.goals.GoalUtils.MIN_NUM_VALID_WINDOWS_FOR_SELF_HEALING)1 GoalUtils.replicaSortName (com.linkedin.kafka.cruisecontrol.analyzer.goals.GoalUtils.replicaSortName)1