我正在使用kafka java客户端0.11.0
和kafka服务器2.11-0.10.2.0
。
我的代码:
KafkaManager
public class KafkaManager {
// Single instance for producer per topic
private static Producer<String, String> karmaProducer = null;
/**
* Initialize Producer
*
* @throws Exception
*/
private static void initProducer() throws Exception {
Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, Constants.kafkaUrl);
props.put(ProducerConfig.RETRIES_CONFIG, Constants.retries);
//props.put(ProducerConfig.BATCH_SIZE_CONFIG, Constants.batchSize);
props.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, Constants.requestTimeout);
//props.put(ProducerConfig.LINGER_MS_CONFIG, Constants.linger);
//props.put(ProducerConfig.ACKS_CONFIG, Constants.acks);
//props.put(ProducerConfig.BUFFER_MEMORY_CONFIG, Constants.bufferMemory);
//props.put(ProducerConfig.MAX_BLOCK_MS_CONFIG, Constants.maxBlock);
props.put(ProducerConfig.CLIENT_ID_CONFIG, Constants.kafkaProducer);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
try {
karmaProducer = new org.apache.kafka.clients.producer.KafkaProducer<String, String>(props);
}
catch (Exception e) {
throw e;
}
}
/**
* get Producer based on topic
*
* @return
* @throws Exception
*/
public static Producer<String, String> getKarmaProducer(String topic) throws Exception {
switch (topic) {
case Constants.topicKarma :
if (karmaProducer == null) {
synchronized (KafkaProducer.class) {
if (karmaProducer == null) {
initProducer();
}
}
}
return karmaProducer;
default:
return null;
}
}
/**
* Flush and close kafka producer
*
* @throws Exception
*/
public static void closeKafkaInstance() throws Exception {
try {
karmaProducer.flush();
karmaProducer.close();
} catch (Exception e) {
throw e;
}
}
}
卡夫卡制片人
public class KafkaProducer {
public void sentToKafka(String topic, String data) {
Producer<String, String> producer = null;
try {
producer = KafkaManager.getKarmaProducer(topic);
ProducerRecord<String, String> producerRecord = new ProducerRecord<String, String>(topic, data);
producer.send(producerRecord);
} catch (Exception e) {
e.printStackTrace();
}
}
}
主类
public class App {
public static void main(String[] args) throws InterruptedException {
System.out.println("Hello World! I am producing to stream " + Constants.topicKarma);
String value = "google";
KafkaProducer kafkaProducer = new KafkaProducer();
for (int i = 1; i <= 1; i++) {
kafkaProducer.sentToKafka(Constants.topicKarma, value + i);
//Thread.sleep(100);
System.out.println("Send data to producer=" + value);
System.out.println("Send data to producer=" + value + i + " to tpoic=" + Constants.topicKarma);
}
}
}
我的问题是什么:
当我的循环长度大约为1000(在类App
中)时,我成功地将数据发送到Kafka主题。
但是当我的循环长度为1或小于10时,我无法向Kafka主题发送数据。注意我没有收到任何错误。
根据我的发现,如果我想向Kafka主题发送一条消息,根据这个程序,我得到了成功的消息,但从未收到有关我主题的消息。
但是如果我使用Thread.sleep(10)(正如我在App类中看到的那样我已经评论过它),那么我就成功发送了关于我主题的数据。
你能解释为什么kafka表现出这种暧昧的行为。
答案 0 :(得分:2)
每次调用KafkaProducer.send()都会返回一个Future。在退出之前,您可以使用最后一个Futures来阻止主线程。更简单的是,您可以在发送所有邮件后调用KafkaProducer.flush(): http://kafka.apache.org/0110/javadoc/org/apache/kafka/clients/producer/KafkaProducer.html#flush()
调用此方法可立即发送所有缓冲记录(即使linger.ms大于0),并在完成与这些记录关联的请求时阻止。
答案 1 :(得分:1)
您可以在退出main之前添加Thread.sleep(100);
吗?
如果我理解正确,那么如果你睡了很短的时间,一切都很顺利。如果是这种情况,则表示您的应用程序在异步发送消息之前被杀死。
答案 2 :(得分:1)
您正面临问题,因为生产者以异步方式执行发送。发送时,将消息放入内部缓冲区以获取更大的批处理,然后一次性发送更多消息。 此批处理功能配置了batch.size和linger.ms,这意味着当批处理大小达到该值或经过了延迟时间时,将发送消息。
我在这里回复了类似的内容:Cannot produce Message when Main Thread sleep less than 1000
即使你说&#34;当我的循环长度大约为1000(在App类中)时,我成功地能够将数据发送到Kafka主题。&#34; ...但也许您没有看到所有已发送的消息,因为最新批次尚未发送。使用较短的循环时,上述条件未及时到达,因此在生产者有足够的时间/批量大小发送之前关闭应用程序。
答案 3 :(得分:0)
将server.properties内的此行从localhost更改为IP地址:
zookeeper.connect=localhost:2181
advertised.listeners=PLAINTEXT://localhost:9092