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