package com.neverwinterdp.kafka.producer;
import java.util.List;
import kafka.cluster.Broker;
import kafka.javaapi.PartitionMetadata;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.neverwinterdp.kafka.tool.KafkaMessageCheckTool;
import com.neverwinterdp.kafka.tool.KafkaMessageSendTool;
import com.neverwinterdp.kafka.tool.KafkaTool;
import com.neverwinterdp.kafka.tool.server.KafkaCluster;
import com.neverwinterdp.util.text.TabularFormater;
/**
* This unit test is used to isolate and show all the kafka producer bugs and limitation.
* The following scenarios are tested
* @author Tuan
*/
public class KafkaProducerPartitionLeaderChangeBugUnitTest {
private KafkaCluster cluster ;
@Before
public void setup() throws Exception {
cluster = new KafkaCluster("./build/kafka", 1, 4);
cluster.setNumOfPartition(5);
cluster.start();
}
@After
public void teardown() throws Exception {
cluster.shutdown();
Thread.sleep(3000);
}
@Test
public void testPartitionLeaderChange() throws Exception {
String TOPIC = "test";
//create topic on brokers 1,2
String[] args = {
"--create", "--topic", TOPIC, "--zookeeper", cluster.getZKConnect(), "--replica-assignment", "1:2,2:1"
//"--partitions", "2", "--replication-factor", "2" parameters have no effect since --replica-assignment has higher priority
};
KafkaTool kafkaTool = new KafkaTool("KafkaTool", cluster.getZKConnect());
kafkaTool.connect();
kafkaTool.createTopic(args);
info(kafkaTool.findTopicMetadata(TOPIC).partitionsMetadata());
String[] sendArgs = {
"--topic" , TOPIC, "--num-partition", "3", "--replication", "2",
"--send-writer-type", "default", "--send-period", "0", "--send-max-per-partition", "20000","--send-max-duration", "60000"
};
KafkaMessageSendTool sendTool = new KafkaMessageSendTool(sendArgs);
sendTool.runAsDeamon();
while(sendTool.getSentCount() <= 0) Thread.sleep(50); //wait to make sure that send tool send some messages
kafkaTool.reassignPartitionReplicas(TOPIC, 0, 4, 3, 2);
//It seems that we do not instruct to change the leader, we loose more messages ?
kafkaTool.moveLeaderToPreferredReplica(TOPIC, 0);
Thread.sleep(1000);
info(kafkaTool.findTopicMetadata(TOPIC).partitionsMetadata());
sendTool.waitForTermination();
Thread.sleep(1000);
String[] checkArgs = {
"--topic", TOPIC,
"--consume-max", Long.toString(sendTool.getSentCount()),
"--zk-connect", cluster.getZKConnect()
};
KafkaMessageCheckTool checkTool = new KafkaMessageCheckTool(checkArgs);
checkTool.run();
System.out.println("Sent count = " + sendTool.getSentCount());
System.out.println("Sent failed count = " + sendTool.getSentFailedCount());
System.out.println("Check count = " + checkTool.getMessageCounter().getTotal());
Assert.assertTrue(checkTool.getMessageCounter().getTotal() < sendTool.getSentCount());
kafkaTool.close();
}
private void info(List<PartitionMetadata> holder) {
String[] header = {
"Partition Id", "Leader", "Replicas"
};
TabularFormater formater = new TabularFormater(header);
formater.setTitle("Partitions");
for(PartitionMetadata sel : holder) {
StringBuilder replicas = new StringBuilder();
for(Broker broker : sel.replicas()) {
if(replicas.length() > 0) replicas.append(",");
replicas.append(broker.port());
}
formater.addRow(sel.partitionId(), sel.leader().port(), replicas.toString());
}
System.out.println(formater.getFormatText());
}
}