Search in sources :

Example 11 with CreatableTopicCollection

use of org.apache.kafka.common.message.CreateTopicsRequestData.CreatableTopicCollection in project kafka by apache.

the class QuorumControllerTest method testFenceMultipleBrokers.

@Test
public void testFenceMultipleBrokers() throws Throwable {
    List<Integer> allBrokers = Arrays.asList(1, 2, 3, 4, 5);
    List<Integer> brokersToKeepUnfenced = Arrays.asList(1);
    List<Integer> brokersToFence = Arrays.asList(2, 3, 4, 5);
    short replicationFactor = 5;
    long sessionTimeoutMillis = 1000;
    try (LocalLogManagerTestEnv logEnv = new LocalLogManagerTestEnv(1, Optional.empty());
        QuorumControllerTestEnv controlEnv = new QuorumControllerTestEnv(logEnv, b -> b.setConfigDefs(CONFIGS), Optional.of(sessionTimeoutMillis))) {
        ListenerCollection listeners = new ListenerCollection();
        listeners.add(new Listener().setName("PLAINTEXT").setHost("localhost").setPort(9092));
        QuorumController active = controlEnv.activeController();
        Map<Integer, Long> brokerEpochs = new HashMap<>();
        for (Integer brokerId : allBrokers) {
            CompletableFuture<BrokerRegistrationReply> reply = active.registerBroker(new BrokerRegistrationRequestData().setBrokerId(brokerId).setClusterId(active.clusterId()).setIncarnationId(Uuid.randomUuid()).setListeners(listeners));
            brokerEpochs.put(brokerId, reply.get().epoch());
        }
        // Brokers are only registered and should still be fenced
        allBrokers.forEach(brokerId -> {
            assertFalse(active.replicationControl().isBrokerUnfenced(brokerId), "Broker " + brokerId + " should have been fenced");
        });
        // Unfence all brokers and create a topic foo
        sendBrokerheartbeat(active, allBrokers, brokerEpochs);
        CreateTopicsRequestData createTopicsRequestData = new CreateTopicsRequestData().setTopics(new CreatableTopicCollection(Collections.singleton(new CreatableTopic().setName("foo").setNumPartitions(1).setReplicationFactor(replicationFactor)).iterator()));
        CreateTopicsResponseData createTopicsResponseData = active.createTopics(createTopicsRequestData).get();
        assertEquals(Errors.NONE, Errors.forCode(createTopicsResponseData.topics().find("foo").errorCode()));
        Uuid topicIdFoo = createTopicsResponseData.topics().find("foo").topicId();
        // Fence some of the brokers
        TestUtils.waitForCondition(() -> {
            sendBrokerheartbeat(active, brokersToKeepUnfenced, brokerEpochs);
            for (Integer brokerId : brokersToFence) {
                if (active.replicationControl().isBrokerUnfenced(brokerId)) {
                    return false;
                }
            }
            return true;
        }, sessionTimeoutMillis * 3, "Fencing of brokers did not process within expected time");
        // Send another heartbeat to the brokers we want to keep alive
        sendBrokerheartbeat(active, brokersToKeepUnfenced, brokerEpochs);
        // At this point only the brokers we want fenced should be fenced.
        brokersToKeepUnfenced.forEach(brokerId -> {
            assertTrue(active.replicationControl().isBrokerUnfenced(brokerId), "Broker " + brokerId + " should have been unfenced");
        });
        brokersToFence.forEach(brokerId -> {
            assertFalse(active.replicationControl().isBrokerUnfenced(brokerId), "Broker " + brokerId + " should have been fenced");
        });
        // Verify the isr and leaders for the topic partition
        int[] expectedIsr = { 1 };
        int[] isrFoo = active.replicationControl().getPartition(topicIdFoo, 0).isr;
        assertTrue(Arrays.equals(isrFoo, expectedIsr), "The ISR for topic foo was " + Arrays.toString(isrFoo) + ". It is expected to be " + Arrays.toString(expectedIsr));
        int fooLeader = active.replicationControl().getPartition(topicIdFoo, 0).leader;
        assertEquals(expectedIsr[0], fooLeader);
    }
}
Also used : ListenerCollection(org.apache.kafka.common.message.BrokerRegistrationRequestData.ListenerCollection) LocalLogManagerTestEnv(org.apache.kafka.metalog.LocalLogManagerTestEnv) Listener(org.apache.kafka.common.message.BrokerRegistrationRequestData.Listener) HashMap(java.util.HashMap) BrokerRegistrationRequestData(org.apache.kafka.common.message.BrokerRegistrationRequestData) BrokerRegistrationReply(org.apache.kafka.metadata.BrokerRegistrationReply) CreateTopicsResponseData(org.apache.kafka.common.message.CreateTopicsResponseData) BrokerEndpoint(org.apache.kafka.common.metadata.RegisterBrokerRecord.BrokerEndpoint) CreatableTopicCollection(org.apache.kafka.common.message.CreateTopicsRequestData.CreatableTopicCollection) Uuid(org.apache.kafka.common.Uuid) CreatableTopic(org.apache.kafka.common.message.CreateTopicsRequestData.CreatableTopic) CreateTopicsRequestData(org.apache.kafka.common.message.CreateTopicsRequestData) Test(org.junit.jupiter.api.Test)

Example 12 with CreatableTopicCollection

use of org.apache.kafka.common.message.CreateTopicsRequestData.CreatableTopicCollection in project kafka by apache.

the class QuorumControllerTest method testSnapshotOnlyAfterConfiguredMinBytes.

@Test
public void testSnapshotOnlyAfterConfiguredMinBytes() throws Throwable {
    final int numBrokers = 4;
    final int maxNewRecordBytes = 1000;
    Map<Integer, Long> brokerEpochs = new HashMap<>();
    try (LocalLogManagerTestEnv logEnv = new LocalLogManagerTestEnv(3, Optional.empty())) {
        try (QuorumControllerTestEnv controlEnv = new QuorumControllerTestEnv(logEnv, builder -> builder.setConfigDefs(CONFIGS).setSnapshotMaxNewRecordBytes(maxNewRecordBytes))) {
            QuorumController active = controlEnv.activeController();
            for (int i = 0; i < numBrokers; i++) {
                BrokerRegistrationReply reply = active.registerBroker(new BrokerRegistrationRequestData().setBrokerId(i).setRack(null).setClusterId(active.clusterId()).setIncarnationId(Uuid.fromString("kxAT73dKQsitIedpiPtwB" + i)).setListeners(new ListenerCollection(Arrays.asList(new Listener().setName("PLAINTEXT").setHost("localhost").setPort(9092 + i)).iterator()))).get();
                brokerEpochs.put(i, reply.epoch());
                assertEquals(new BrokerHeartbeatReply(true, false, false, false), active.processBrokerHeartbeat(new BrokerHeartbeatRequestData().setWantFence(false).setBrokerEpoch(brokerEpochs.get(i)).setBrokerId(i).setCurrentMetadataOffset(100000L)).get());
            }
            assertTrue(logEnv.appendedBytes() < maxNewRecordBytes, String.format("%s appended bytes is not less than %s max new record bytes", logEnv.appendedBytes(), maxNewRecordBytes));
            // Keep creating topic until we reached the max bytes limit
            int counter = 0;
            while (logEnv.appendedBytes() < maxNewRecordBytes) {
                counter += 1;
                String topicName = String.format("foo-%s", counter);
                active.createTopics(new CreateTopicsRequestData().setTopics(new CreatableTopicCollection(Collections.singleton(new CreatableTopic().setName(topicName).setNumPartitions(-1).setReplicationFactor((short) -1).setAssignments(new CreatableReplicaAssignmentCollection(Arrays.asList(new CreatableReplicaAssignment().setPartitionIndex(0).setBrokerIds(Arrays.asList(0, 1, 2)), new CreatableReplicaAssignment().setPartitionIndex(1).setBrokerIds(Arrays.asList(1, 2, 0))).iterator()))).iterator()))).get();
            }
            logEnv.waitForLatestSnapshot();
        }
    }
}
Also used : BrokerHeartbeatReply(org.apache.kafka.metadata.BrokerHeartbeatReply) ListenerCollection(org.apache.kafka.common.message.BrokerRegistrationRequestData.ListenerCollection) LocalLogManagerTestEnv(org.apache.kafka.metalog.LocalLogManagerTestEnv) Listener(org.apache.kafka.common.message.BrokerRegistrationRequestData.Listener) HashMap(java.util.HashMap) BrokerRegistrationRequestData(org.apache.kafka.common.message.BrokerRegistrationRequestData) BrokerRegistrationReply(org.apache.kafka.metadata.BrokerRegistrationReply) BrokerEndpoint(org.apache.kafka.common.metadata.RegisterBrokerRecord.BrokerEndpoint) CreatableTopicCollection(org.apache.kafka.common.message.CreateTopicsRequestData.CreatableTopicCollection) BrokerHeartbeatRequestData(org.apache.kafka.common.message.BrokerHeartbeatRequestData) CreatableTopic(org.apache.kafka.common.message.CreateTopicsRequestData.CreatableTopic) CreatableReplicaAssignment(org.apache.kafka.common.message.CreateTopicsRequestData.CreatableReplicaAssignment) CreateTopicsRequestData(org.apache.kafka.common.message.CreateTopicsRequestData) CreatableReplicaAssignmentCollection(org.apache.kafka.common.message.CreateTopicsRequestData.CreatableReplicaAssignmentCollection) Test(org.junit.jupiter.api.Test)

Example 13 with CreatableTopicCollection

use of org.apache.kafka.common.message.CreateTopicsRequestData.CreatableTopicCollection in project kafka by apache.

the class KafkaAdminClient method getCreateTopicsCall.

private Call getCreateTopicsCall(final CreateTopicsOptions options, final Map<String, KafkaFutureImpl<TopicMetadataAndConfig>> futures, final CreatableTopicCollection topics, final Map<String, ThrottlingQuotaExceededException> quotaExceededExceptions, final long now, final long deadline) {
    return new Call("createTopics", deadline, new ControllerNodeProvider()) {

        @Override
        public CreateTopicsRequest.Builder createRequest(int timeoutMs) {
            return new CreateTopicsRequest.Builder(new CreateTopicsRequestData().setTopics(topics).setTimeoutMs(timeoutMs).setValidateOnly(options.shouldValidateOnly()));
        }

        @Override
        public void handleResponse(AbstractResponse abstractResponse) {
            // Check for controller change
            handleNotControllerError(abstractResponse);
            // Handle server responses for particular topics.
            final CreateTopicsResponse response = (CreateTopicsResponse) abstractResponse;
            final CreatableTopicCollection retryTopics = new CreatableTopicCollection();
            final Map<String, ThrottlingQuotaExceededException> retryTopicQuotaExceededExceptions = new HashMap<>();
            for (CreatableTopicResult result : response.data().topics()) {
                KafkaFutureImpl<TopicMetadataAndConfig> future = futures.get(result.name());
                if (future == null) {
                    log.warn("Server response mentioned unknown topic {}", result.name());
                } else {
                    ApiError error = new ApiError(result.errorCode(), result.errorMessage());
                    if (error.isFailure()) {
                        if (error.is(Errors.THROTTLING_QUOTA_EXCEEDED)) {
                            ThrottlingQuotaExceededException quotaExceededException = new ThrottlingQuotaExceededException(response.throttleTimeMs(), error.messageWithFallback());
                            if (options.shouldRetryOnQuotaViolation()) {
                                retryTopics.add(topics.find(result.name()).duplicate());
                                retryTopicQuotaExceededExceptions.put(result.name(), quotaExceededException);
                            } else {
                                future.completeExceptionally(quotaExceededException);
                            }
                        } else {
                            future.completeExceptionally(error.exception());
                        }
                    } else {
                        TopicMetadataAndConfig topicMetadataAndConfig;
                        if (result.topicConfigErrorCode() != Errors.NONE.code()) {
                            topicMetadataAndConfig = new TopicMetadataAndConfig(Errors.forCode(result.topicConfigErrorCode()).exception());
                        } else if (result.numPartitions() == CreateTopicsResult.UNKNOWN) {
                            topicMetadataAndConfig = new TopicMetadataAndConfig(new UnsupportedVersionException("Topic metadata and configs in CreateTopics response not supported"));
                        } else {
                            List<CreatableTopicConfigs> configs = result.configs();
                            Config topicConfig = new Config(configs.stream().map(this::configEntry).collect(Collectors.toSet()));
                            topicMetadataAndConfig = new TopicMetadataAndConfig(result.topicId(), result.numPartitions(), result.replicationFactor(), topicConfig);
                        }
                        future.complete(topicMetadataAndConfig);
                    }
                }
            }
            // If there are topics to retry, retry them; complete unrealized futures otherwise.
            if (retryTopics.isEmpty()) {
                // The server should send back a response for every topic. But do a sanity check anyway.
                completeUnrealizedFutures(futures.entrySet().stream(), topic -> "The controller response did not contain a result for topic " + topic);
            } else {
                final long now = time.milliseconds();
                final Call call = getCreateTopicsCall(options, futures, retryTopics, retryTopicQuotaExceededExceptions, now, deadline);
                runnable.call(call, now);
            }
        }

        private ConfigEntry configEntry(CreatableTopicConfigs config) {
            return new ConfigEntry(config.name(), config.value(), configSource(DescribeConfigsResponse.ConfigSource.forId(config.configSource())), config.isSensitive(), config.readOnly(), Collections.emptyList(), null, null);
        }

        @Override
        void handleFailure(Throwable throwable) {
            // If there were any topics retries due to a quota exceeded exception, we propagate
            // the initial error back to the caller if the request timed out.
            maybeCompleteQuotaExceededException(options.shouldRetryOnQuotaViolation(), throwable, futures, quotaExceededExceptions, (int) (time.milliseconds() - now));
            // Fail all the other remaining futures
            completeAllExceptionally(futures.values(), throwable);
        }
    };
}
Also used : CreateTopicsResponse(org.apache.kafka.common.requests.CreateTopicsResponse) AbstractResponse(org.apache.kafka.common.requests.AbstractResponse) HashMap(java.util.HashMap) TopicMetadataAndConfig(org.apache.kafka.clients.admin.CreateTopicsResult.TopicMetadataAndConfig) MetricConfig(org.apache.kafka.common.metrics.MetricConfig) ChannelBuilder(org.apache.kafka.common.network.ChannelBuilder) ThrottlingQuotaExceededException(org.apache.kafka.common.errors.ThrottlingQuotaExceededException) CreatableTopicCollection(org.apache.kafka.common.message.CreateTopicsRequestData.CreatableTopicCollection) CreateTopicsRequest(org.apache.kafka.common.requests.CreateTopicsRequest) TopicMetadataAndConfig(org.apache.kafka.clients.admin.CreateTopicsResult.TopicMetadataAndConfig) CreateTopicsRequestData(org.apache.kafka.common.message.CreateTopicsRequestData) CreatableTopicResult(org.apache.kafka.common.message.CreateTopicsResponseData.CreatableTopicResult) CreatableTopicConfigs(org.apache.kafka.common.message.CreateTopicsResponseData.CreatableTopicConfigs) LinkedList(java.util.LinkedList) ArrayList(java.util.ArrayList) List(java.util.List) ApiError(org.apache.kafka.common.requests.ApiError) UnsupportedVersionException(org.apache.kafka.common.errors.UnsupportedVersionException)

Aggregations

CreatableTopicCollection (org.apache.kafka.common.message.CreateTopicsRequestData.CreatableTopicCollection)13 CreateTopicsRequestData (org.apache.kafka.common.message.CreateTopicsRequestData)11 CreatableTopic (org.apache.kafka.common.message.CreateTopicsRequestData.CreatableTopic)11 Test (org.junit.jupiter.api.Test)10 HashMap (java.util.HashMap)9 LocalLogManagerTestEnv (org.apache.kafka.metalog.LocalLogManagerTestEnv)8 BrokerRegistrationRequestData (org.apache.kafka.common.message.BrokerRegistrationRequestData)6 Listener (org.apache.kafka.common.message.BrokerRegistrationRequestData.Listener)6 ListenerCollection (org.apache.kafka.common.message.BrokerRegistrationRequestData.ListenerCollection)6 BrokerRegistrationReply (org.apache.kafka.metadata.BrokerRegistrationReply)6 Uuid (org.apache.kafka.common.Uuid)5 BrokerHeartbeatRequestData (org.apache.kafka.common.message.BrokerHeartbeatRequestData)5 CreateTopicsResponseData (org.apache.kafka.common.message.CreateTopicsResponseData)5 BrokerHeartbeatReply (org.apache.kafka.metadata.BrokerHeartbeatReply)5 CreatableReplicaAssignmentCollection (org.apache.kafka.common.message.CreateTopicsRequestData.CreatableReplicaAssignmentCollection)4 BrokerEndpoint (org.apache.kafka.common.metadata.RegisterBrokerRecord.BrokerEndpoint)4 List (java.util.List)3 CreatableReplicaAssignment (org.apache.kafka.common.message.CreateTopicsRequestData.CreatableReplicaAssignment)3 ApiError (org.apache.kafka.common.requests.ApiError)3 Iterator (java.util.Iterator)2