Apache kafka恰好一次实现不发送消息

时间:2017-07-12 03:26:10

标签: apache-kafka kafka-producer-api idempotent

我正试图用幂等生产者& amp;其中一家银行使用的交易。

我创建了这样的制作人:

String topicName = "exonce";

Properties props = new Properties();

props.put("bootstrap.servers", "localhost:9092");
props.put("acks", "all");
props.put("retries", 1);
props.put("batch.size", 16384);
props.put("linger.ms", 1);
props.put("buffer.memory", 33554432);
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

props.put("enable.idempotence", "true");
props.put("transactional.id", "1");
props.put("acks", "all");
props.put("transaction.timeout.ms","160000");

Thread.currentThread().setContextClassLoader(null);
Producer<String, String> producer = new KafkaProducer
   <String, String>(props);
producer.initTransactions();
producer.beginTransaction();

producer.send(new ProducerRecord<String, String>(topicName,           "val_"));

producer.commitTransaction();
System.out.println("Message sent successfully");
producer.close();

但我无法在消费者方面得到任何东西。我也没看到sysout:&#34;消息发送成功&#34;至少sysout应该来/显示。

程序没有结束它等待发生的事情(没有错误/异常)。在等待:producer.initTransactions();线

这是日志:

  

17/07/12 08:46:36 INFO producer.ProducerConfig:ProducerConfig值:     acks = all

     

batch.size = 16384

     

bootstrap.servers = [localhost:9092]

     

buffer.memory = 33554432

     

client.id =

     

compression.type = none

     

connections.max.idle.ms = 540000

     

enable.idempotence = true

     

interceptor.classes = null

     

key.serializer = class org.apache.kafka.common.serialization.StringSerializer

     

linger.ms = 1

     

max.block.ms = 60000

     

max.in.flight.requests.per.connection = 5

     

max.request.size = 1048576

     

metadata.max.age.ms = 300000

     

metric.reporters = []

     

metrics.num.samples = 2

     

metrics.recording.level = INFO

     

metrics.sample.window.ms = 30000

     

partitioner.class = class org.apache.kafka.clients.producer.internals.DefaultPartitioner

     

receive.buffer.bytes = 32768

     

reconnect.backoff.max.ms = 1000

     

reconnect.backoff.ms = 50

     

request.timeout.ms = 30000

     

retries = 1

     

retry.backoff.ms = 100

     

transaction.timeout.ms = 160000

     

transactional.id = 1

     

value.serializer = class org.apache.kafka.common.serialization.StringSerializer

     

17/07/12 08:46:36 INFO producer.KafkaProducer:实例化一个事务生产者。

     

17/07/12 08:46:36 INFO producer.KafkaProducer:由于启用了idempontence,所以将默认的max.in.flight.requests.per.connection覆盖为1。

     

17/07/12 08:46:37 INFO utils.AppInfoParser:Kafka版本:0.11.0.0

     

17/07/12 08:46:37 INFO utils.AppInfoParser:Kafka commitId:cb8625948210849f

     

17/07/12 08:46:37 INFO internals.TransactionManager:[TransactionalId 1] ProducerId设置为-1,epoch -1

我不确定我在这里犯了什么错误。

我正在使用kafka-0.11.0.0

如果您需要更多信息,请告诉我。

感谢您的帮助&amp;支持。

由于

拉​​吉

3 个答案:

答案 0 :(得分:2)

这是单节点安装吗?你能检查一下server.log是否正确创建了__transaction_state主题吗?它需要3个副本才能创建,并且只在第一个initTransactions请求中创建。因此,如果您没有足够的代理,主题的创建将失败,initTransactions请求可能会永久阻止。

答案 1 :(得分:1)

这是我在遵循提示默认情况下需要3个经纪人的提示之后发现的。此外,默认情况下,事务需要同步2个副本。

在我基于Docker的环境中,我因此减少了我的经纪人的这两个设置:

KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1

这些设置对应于https://kafka.apache.org/0110/documentation.html#brokerconfigs

中记录的设置
transaction.state.log.min.isr
transaction.state.log.replication.factor

注意:ISR代表同步副本

还有一个:如果您使用的是汇合的默认平台设置(而不是泊坞窗容器),这些设置已经预先配置好了。

答案 2 :(得分:-1)

尝试在javadoc中运行示例的更新答案,作为使用0.11客户端协议正确配置代理0.11的测试

 Properties props = new Properties();


props.put("bootstrap.servers", "localhost:9092");
 props.put("transactional.id", "my-transactional-id");
 Producer<String, String> producer = new KafkaProducer<>(props, new StringSerializer(), new StringSerializer());

 producer.initTransactions();

 try {
     producer.beginTransaction();
     for (int i = 0; i < 100; i++)
         producer.send(new ProducerRecord<>("my-topic", Integer.toString(i), Integer.toString(i)));
     producer.commitTransaction();
 } catch (ProducerFencedException | OutOfOrderSequenceException | AuthorizationException e) {
     // We can't recover from these exceptions, so our only option is to close the producer and exit.
     producer.close();
 } catch (KafkaException e) {
     // For all other exceptions, just abort the transaction and try again.
     producer.abortTransaction();
 }
 producer.close();