Browse Source
feat: Add standalone Java SeekToBeginning test to reproduce the issue
feat: Add standalone Java SeekToBeginning test to reproduce the issue
Created: - SeekToBeginningTest.java: Standalone Java test that reproduces the seekToBeginning() hang - Dockerfile.seektest: Docker setup for running the test - pom.xml: Maven build configuration - Updated docker-compose.yml to include seek-test service This test simulates what Schema Registry does: 1. Create KafkaConsumer connected to gateway 2. Assign to _schemas topic partition 0 3. Call seekToBeginning() 4. Poll for records Expected behavior: Should send ListOffsets and then Fetch Actual behavior: Blocks indefinitely after seekToBeginning()pull/7329/head
4 changed files with 171 additions and 0 deletions
-
20test/kafka/kafka-client-loadtest/Dockerfile.seektest
-
73test/kafka/kafka-client-loadtest/SeekToBeginningTest.java
-
18test/kafka/kafka-client-loadtest/docker-compose.yml
-
60test/kafka/kafka-client-loadtest/pom.xml
@ -0,0 +1,20 @@ |
|||
FROM openjdk:11-jdk-slim |
|||
|
|||
# Install Maven |
|||
RUN apt-get update && apt-get install -y maven && rm -rf /var/lib/apt/lists/* |
|||
|
|||
WORKDIR /app |
|||
|
|||
# Create source directory |
|||
RUN mkdir -p src/main/java |
|||
|
|||
# Copy source and build files |
|||
COPY SeekToBeginningTest.java src/main/java/ |
|||
COPY pom.xml . |
|||
|
|||
# Compile and package |
|||
RUN mvn clean package -DskipTests |
|||
|
|||
# Run the test |
|||
ENTRYPOINT ["java", "-cp", "target/seek-test.jar", "SeekToBeginningTest"] |
|||
CMD ["kafka-gateway:9093"] |
@ -0,0 +1,73 @@ |
|||
import org.apache.kafka.clients.consumer.*; |
|||
import org.apache.kafka.common.TopicPartition; |
|||
import org.apache.kafka.common.serialization.ByteArrayDeserializer; |
|||
import java.util.*; |
|||
|
|||
/** |
|||
* Test program to reproduce the seekToBeginning() hang issue |
|||
* |
|||
* This simulates what Schema Registry does: |
|||
* 1. Create KafkaConsumer |
|||
* 2. Assign to partition |
|||
* 3. Call seekToBeginning() |
|||
* 4. Poll for records |
|||
* |
|||
* Expected behavior: Consumer should send ListOffsets and then Fetch requests |
|||
* Observed behavior: Consumer sends InitProducerId but not ListOffsets, then |
|||
* hangs |
|||
*/ |
|||
public class SeekToBeginningTest { |
|||
public static void main(String[] args) throws Exception { |
|||
String bootstrapServers = "localhost:9093"; |
|||
String topicName = "_schemas"; |
|||
|
|||
if (args.length > 0) { |
|||
bootstrapServers = args[0]; |
|||
} |
|||
|
|||
Properties props = new Properties(); |
|||
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers); |
|||
props.put(ConsumerConfig.GROUP_ID_CONFIG, "test-seek-group"); |
|||
props.put(ConsumerConfig.CLIENT_ID_CONFIG, "test-seek-client"); |
|||
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); |
|||
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false"); |
|||
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, ByteArrayDeserializer.class); |
|||
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ByteArrayDeserializer.class); |
|||
props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "45000"); |
|||
props.put(ConsumerConfig.REQUEST_TIMEOUT_MS_CONFIG, "60000"); |
|||
|
|||
System.out.println("[TEST] Creating KafkaConsumer connecting to " + bootstrapServers); |
|||
KafkaConsumer<byte[], byte[]> consumer = new KafkaConsumer<>(props); |
|||
|
|||
TopicPartition tp = new TopicPartition(topicName, 0); |
|||
List<TopicPartition> partitions = Arrays.asList(tp); |
|||
|
|||
System.out.println("[TEST] Assigning to partition: " + tp); |
|||
consumer.assign(partitions); |
|||
|
|||
System.out.println("[TEST] Calling seekToBeginning()..."); |
|||
long startTime = System.currentTimeMillis(); |
|||
consumer.seekToBeginning(partitions); |
|||
long seekTime = System.currentTimeMillis() - startTime; |
|||
System.out.println("[TEST] seekToBeginning() completed in " + seekTime + "ms"); |
|||
|
|||
System.out.println("[TEST] Starting poll loop (30 second timeout per poll)..."); |
|||
for (int i = 0; i < 3; i++) { |
|||
System.out.println("[POLL " + (i + 1) + "] Polling for records..."); |
|||
long pollStart = System.currentTimeMillis(); |
|||
ConsumerRecords<byte[], byte[]> records = consumer.poll(java.time.Duration.ofSeconds(30)); |
|||
long pollTime = System.currentTimeMillis() - pollStart; |
|||
System.out.println("[POLL " + (i + 1) + "] Got " + records.count() + " records in " + pollTime + "ms"); |
|||
|
|||
for (ConsumerRecord<byte[], byte[]> record : records) { |
|||
System.out.println(" [RECORD] offset=" + record.offset() + ", key.len=" + |
|||
(record.key() != null ? record.key().length : 0) + |
|||
", value.len=" + (record.value() != null ? record.value().length : 0)); |
|||
} |
|||
} |
|||
|
|||
System.out.println("[TEST] Closing consumer..."); |
|||
consumer.close(); |
|||
System.out.println("[TEST] Done!"); |
|||
} |
|||
} |
@ -0,0 +1,60 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
|
|||
<groupId>io.confluent.test</groupId> |
|||
<artifactId>seek-test</artifactId> |
|||
<version>1.0</version> |
|||
|
|||
<properties> |
|||
<maven.compiler.source>11</maven.compiler.source> |
|||
<maven.compiler.target>11</maven.compiler.target> |
|||
<kafka.version>3.6.0</kafka.version> |
|||
</properties> |
|||
|
|||
<dependencies> |
|||
<dependency> |
|||
<groupId>org.apache.kafka</groupId> |
|||
<artifactId>kafka-clients</artifactId> |
|||
<version>${kafka.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.slf4j</groupId> |
|||
<artifactId>slf4j-simple</artifactId> |
|||
<version>2.0.0</version> |
|||
</dependency> |
|||
</dependencies> |
|||
|
|||
<build> |
|||
<plugins> |
|||
<plugin> |
|||
<groupId>org.apache.maven.plugins</groupId> |
|||
<artifactId>maven-compiler-plugin</artifactId> |
|||
<version>3.8.1</version> |
|||
</plugin> |
|||
<plugin> |
|||
<groupId>org.apache.maven.plugins</groupId> |
|||
<artifactId>maven-shade-plugin</artifactId> |
|||
<version>3.2.4</version> |
|||
<executions> |
|||
<execution> |
|||
<phase>package</phase> |
|||
<goals> |
|||
<goal>shade</goal> |
|||
</goals> |
|||
<configuration> |
|||
<transformers> |
|||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> |
|||
<mainClass>SeekToBeginningTest</mainClass> |
|||
</transformer> |
|||
</transformers> |
|||
<finalName>seek-test</finalName> |
|||
</configuration> |
|||
</execution> |
|||
</executions> |
|||
</plugin> |
|||
</plugins> |
|||
</build> |
|||
</project> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue