AndrewJSchofield commented on code in PR #19811: URL: https://github.com/apache/kafka/pull/19811#discussion_r2120617044
########## tests/kafkatest/tests/core/share_consume_bench_test.py: ########## @@ -0,0 +1,179 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +from ducktape.utils.util import wait_until +from ducktape.mark import matrix +from ducktape.mark.resource import cluster +from ducktape.tests.test import Test +from kafkatest.services.kafka import KafkaService, quorum +from kafkatest.services.trogdor.produce_bench_workload import ProduceBenchWorkloadService, ProduceBenchWorkloadSpec +from kafkatest.services.trogdor.share_consume_bench_workload import ShareConsumeBenchWorkloadService, ShareConsumeBenchWorkloadSpec +from kafkatest.services.trogdor.task_spec import TaskSpec +from kafkatest.services.trogdor.trogdor import TrogdorService + + +class ShareConsumeBenchTest(Test): + def __init__(self, test_context): + """:type test_context: ducktape.tests.test.TestContext""" + super(ShareConsumeBenchTest, self).__init__(test_context) + self.kafka = KafkaService(test_context, num_nodes=3, zk=None) + self.producer_workload_service = ProduceBenchWorkloadService(test_context, self.kafka) + self.share_consumer_workload_service = ShareConsumeBenchWorkloadService(test_context, self.kafka) + self.share_consumer_workload_service_2 = ShareConsumeBenchWorkloadService(test_context, self.kafka) Review Comment: What is the purpose of this second workload service? Can it be removed? ########## tests/kafkatest/services/kafka/kafka.py: ########## @@ -1764,13 +1764,30 @@ def list_share_groups(self, node=None, command_config=None, state=None): cmd = fix_opts_for_new_jvm(node) cmd += "%s --bootstrap-server %s %s --list" % \ - (share_group_script, - self.bootstrap_servers(self.security_protocol), - command_config) + (share_group_script, + self.bootstrap_servers(self.security_protocol), + command_config) if state is not None: cmd += " --state %s" % state return self.run_cli_tool(node, cmd) + def set_group_offset_reset_strategy(self, group, strategy=None, node=None): Review Comment: nit: `set_share_group_offset_reset_strategy`. ########## tests/kafkatest/tests/core/share_consume_bench_test.py: ########## @@ -0,0 +1,179 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +from ducktape.utils.util import wait_until +from ducktape.mark import matrix +from ducktape.mark.resource import cluster +from ducktape.tests.test import Test +from kafkatest.services.kafka import KafkaService, quorum +from kafkatest.services.trogdor.produce_bench_workload import ProduceBenchWorkloadService, ProduceBenchWorkloadSpec +from kafkatest.services.trogdor.share_consume_bench_workload import ShareConsumeBenchWorkloadService, ShareConsumeBenchWorkloadSpec +from kafkatest.services.trogdor.task_spec import TaskSpec +from kafkatest.services.trogdor.trogdor import TrogdorService + + +class ShareConsumeBenchTest(Test): + def __init__(self, test_context): + """:type test_context: ducktape.tests.test.TestContext""" + super(ShareConsumeBenchTest, self).__init__(test_context) + self.kafka = KafkaService(test_context, num_nodes=3, zk=None) + self.producer_workload_service = ProduceBenchWorkloadService(test_context, self.kafka) + self.share_consumer_workload_service = ShareConsumeBenchWorkloadService(test_context, self.kafka) + self.share_consumer_workload_service_2 = ShareConsumeBenchWorkloadService(test_context, self.kafka) + self.topics_with_multiple_partitions = {"share_consume_bench_topic[0-5]": {"numPartitions": 5, "replicationFactor": 3}} + self.topic_with_single_partitions = {"share_consume_bench_topic6": {"numPartitions": 1, "replicationFactor": 3}} + self.trogdor = TrogdorService(context=self.test_context, + client_services=[self.kafka, self.producer_workload_service, + self.share_consumer_workload_service, + self.share_consumer_workload_service_2]) + self.share_group="share-group" + + def setUp(self): + self.trogdor.start() + self.kafka.start() + + def teardown(self): + self.trogdor.stop() + self.kafka.stop() + + def produce_messages(self, topics, max_messages=10000): + produce_spec = ProduceBenchWorkloadSpec(0, TaskSpec.MAX_DURATION_MS, + self.producer_workload_service.producer_node, + self.producer_workload_service.bootstrap_servers, + target_messages_per_sec=1000, + max_messages=max_messages, + producer_conf={}, + admin_client_conf={}, + common_client_conf={}, + inactive_topics={}, + active_topics=topics) + produce_workload = self.trogdor.create_task("produce_workload", produce_spec) + produce_workload.wait_for_done(timeout_sec=180) + self.logger.debug("Produce workload finished") + + @cluster(num_nodes=10) + @matrix( + metadata_quorum=[quorum.isolated_kraft], + use_share_groups=[True], + ) + def test_share_consume_bench(self, metadata_quorum, use_share_groups=True): + """ + Runs a ShareConsumeBench workload to consume messages + """ + self.produce_messages(self.topics_with_multiple_partitions) + share_consume_spec = ShareConsumeBenchWorkloadSpec(0, TaskSpec.MAX_DURATION_MS, + self.share_consumer_workload_service.share_consumer_node, + self.share_consumer_workload_service.bootstrap_servers, + target_messages_per_sec=1000, + max_messages=10000, + consumer_conf={}, + admin_client_conf={}, + common_client_conf={}, + active_topics=["share_consume_bench_topic[0-5]"], + share_group=self.share_group) + wait_until(lambda: self.kafka.set_group_offset_reset_strategy(group=self.share_group, strategy="earliest"), + timeout_sec=20, backoff_sec=2, err_msg="auto.offset.reset not set to earliest") + share_consume_workload = self.trogdor.create_task("share_consume_workload", share_consume_spec) + share_consume_workload.wait_for_done(timeout_sec=360) + self.logger.debug("Share consume workload finished") + tasks = self.trogdor.tasks() + self.logger.info("TASKS: %s\n" % json.dumps(tasks, sort_keys=True, indent=2)) + + @cluster(num_nodes=10) + @matrix( + metadata_quorum=[quorum.isolated_kraft], + use_share_groups=[True], + ) + def test_two_share_consumers_in_a_group_topics(self, metadata_quorum, use_share_groups=True): + """ + Runs two share consumers in the same share group to read messages from topics. + """ + self.produce_messages(self.topics_with_multiple_partitions) + share_consume_spec = ShareConsumeBenchWorkloadSpec(0, TaskSpec.MAX_DURATION_MS, + self.share_consumer_workload_service.share_consumer_node, + self.share_consumer_workload_service.bootstrap_servers, + target_messages_per_sec=1000, + max_messages=2000, # both should read at least 2k messages + consumer_conf={}, + admin_client_conf={}, + common_client_conf={}, + threads_per_worker=2, + active_topics=["share_consume_bench_topic[0-5]"], + share_group=self.share_group) + wait_until(lambda: self.kafka.set_group_offset_reset_strategy(group=self.share_group, strategy="earliest"), + timeout_sec=20, backoff_sec=2, err_msg="auto.offset.reset not set to earliest") + share_consume_workload = self.trogdor.create_task("share_consume_workload", share_consume_spec) + share_consume_workload.wait_for_done(timeout_sec=360) + self.logger.debug("Share consume workload finished") + tasks = self.trogdor.tasks() + self.logger.info("TASKS: %s\n" % json.dumps(tasks, sort_keys=True, indent=2)) + + @cluster(num_nodes=10) + @matrix( + metadata_quorum=[quorum.isolated_kraft], + use_share_groups=[True], + ) + def test_one_share_consumer_subscribed_to_single_topic(self, metadata_quorum, use_share_groups=True): + """ + Runs one share consumers in a share group to read messages from topic with single partition. + """ + self.produce_messages(self.topic_with_single_partitions) + share_consume_spec = ShareConsumeBenchWorkloadSpec(0, TaskSpec.MAX_DURATION_MS, + self.share_consumer_workload_service.share_consumer_node, + self.share_consumer_workload_service.bootstrap_servers, + target_messages_per_sec=1000, + max_messages=10000, + consumer_conf={}, + admin_client_conf={}, + common_client_conf={}, + active_topics=["share_consume_bench_topic6"], + share_group=self.share_group) + wait_until(lambda: self.kafka.set_group_offset_reset_strategy(group=self.share_group, strategy="earliest"), + timeout_sec=20, backoff_sec=2, err_msg="auto.offset.reset not set to earliest") + share_consume_workload = self.trogdor.create_task("share_consume_workload", share_consume_spec) + share_consume_workload.wait_for_done(timeout_sec=360) + self.logger.debug("Share consume workload finished") + tasks = self.trogdor.tasks() + self.logger.info("TASKS: %s\n" % json.dumps(tasks, sort_keys=True, indent=2)) + + @cluster(num_nodes=10) + @matrix( + metadata_quorum=[quorum.isolated_kraft], + use_share_groups=[True], + ) + def test_multiple_share_consumer_subscribed_to_single_topic(self, metadata_quorum, use_share_groups=True): Review Comment: nit: `multiple_share_consumers_` -- 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: jira-unsubscr...@kafka.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org