Apache kafka ApacheKafka精确一次实现不发送消息

Apache kafka ApacheKafka精确一次实现不发送消息,apache-kafka,kafka-producer-api,idempotent,Apache Kafka,Kafka Producer Api,Idempotent,我正试图为一个banks用例使用幂等生产者&事务实现一次语义 我创建了这样的制片人: 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.

我正试图为一个banks用例使用幂等生产者&事务实现一次语义

我创建了这样的制片人:

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();
String-topicName=“exonce”;
Properties props=新属性();
put(“bootstrap.servers”,“localhost:9092”);
道具放置(“阿克斯”、“全部”);
道具放置(“重试”,1);
道具放置(“批量大小”,16384);
道具放置(“玲儿小姐”,1);
props.put(“buffer.memory”,33554432);
put(“key.serializer”、“org.apache.kafka.common.serialization.StringSerializer”);
put(“value.serializer”、“org.apache.kafka.common.serialization.StringSerializer”);
props.put(“使能.幂等”,“真”);
props.put(“transactional.id”、“1”);
道具放置(“阿克斯”、“全部”);
props.put(“transaction.timeout.ms”,“160000”);
Thread.currentThread().setContextClassLoader(null);
制作人=新卡夫卡制作人
(道具);
producer.initTransactions();
producer.beginTransaction();
生产商发送(新生产商记录(主题名称,“val”);
producer.commitTransaction();
System.out.println(“消息发送成功”);
producer.close();
但我无法在消费者端获得任何信息&而且我也看不到sysout:“消息发送成功”,至少sysout应该出现/显示

程序没有结束,它在等待某些事情发生(没有错误/异常)。正在等待:producer.initTransactions();行

这是日志:

17/07/12 08:46:36信息生产者。生产者配置:生产者配置值: acks=全部

batch.size=16384

bootstrap.servers=[localhost:9092]

buffer.memory=33554432

client.id=

compression.type=none

connections.max.idle.ms=540000

enable.idemponence=true

interceptor.classes=null

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

linger.ms=1

最大block.ms=60000

最大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

重新连接.backoff.max.ms=1000

重新连接.backoff.ms=50

request.timeout.ms=30000

重试次数=1

retry.backoff.ms=100

transaction.timeout.ms=160000

事务id=1

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

17/07/12 08:46:36信息生产者。KafkaProducer:实例化了事务生产者

17/07/12 08:46:36 INFO producer.KafkaProducer:将默认的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:卡夫卡委员会:cb8625948210849f

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

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

我使用的是卡夫卡-0.11.0.0

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

感谢您的帮助和支持

谢谢


Raj

更新了答案,尝试在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();
Properties=newproperties();
put(“bootstrap.servers”,“localhost:9092”);
props.put(“transactional.id”、“我的事务id”);
Producer-Producer=new-KafkaProducer(props,new-StringSerializer(),new-StringSerializer());
producer.initTransactions();
试一试{
producer.beginTransaction();
对于(int i=0;i<100;i++)
producer.send(新ProducerRecord(“我的主题”,Integer.toString(i),Integer.toString(i));
producer.commitTransaction();
}捕获(ProducerFencedException |无序顺序异常|授权异常e){
//我们无法从这些异常中恢复,因此我们唯一的选择是关闭生产者并退出。
producer.close();
}捕获(卡夫卡例外){
//对于所有其他异常,只需中止事务并重试。
producer.abortTransaction();
}
producer.close();

这是单节点安装吗?您能否检查server.log以了解
\u事务\u状态
主题是否正确创建?它需要3个副本才能创建,并且仅在第一次
initTransactions
请求时创建。因此,如果没有足够的代理,主题的创建将失败,
initTransactions
请求可能会永远被阻止。

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

因此,在基于Docker的环境中,我减少了代理上的这两个设置:

KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
这些设置与中记录的设置相对应

注意:ISR表示同步副本


还有一点:如果您使用confluent的默认平台设置(而不是docker容器),这些设置已经预配置好了。

我不这么认为,javadoc:public void close()“关闭此生产者。此方法将阻止所有以前发送的请求完成”感谢您的回复@hans jespersen&@michal borowiecki,正如我在原始问题中所说的,执行并没有跨越producer.initTransactions()调用。我进一步添加了调试点,发现编码正在等待:
public void initTransactions(){if(transactionManager==null)抛出新的非法状态异常(“Cannot-cal”)
transaction.state.log.min.isr
transaction.state.log.replication.factor