携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第29天,点击查看活动详情
生产者
Producer,产生消息。
Java生产者是如何管理TCP连接的?
何时创建TCP连接?
在创建KafkaProducer
Properties props = new Properties ();
props.put(“参数1”, “参数1的值”);
props.put(“参数2”, “参数2的值”);
……try (Producer producer = new KafkaProducer<>(props)) { producer.send(new ProducerRecord(……), callback);
……}
在创建KafkaProducer实例时,生产者应用会在后台创建并启动一个名为Sender的线程,该线程开始运行时首先会创建与Broker的连接。因为Producer都不知道给哪个主题发消息,所以它会连接bootstrap.servers参数指定的所有Broker,等更新了集群的元数据信息之后,如果发现与某些Broker当前没有连接,那么它就会创建一个TCP连接。当要发送消息时,Producer发现尚不存在与目标Broker的连接,也会创建一个。
何时关闭TCP连接?
- 用户主动关闭 调用producer.close()方法或者关闭“Producer”应用等。
- Kafka自动关闭 这与Producer端参数connections.max.idle.ms有关,如果在设置是时间内没有请求和心跳,那么Kafka会主动帮你把TCP连接关闭。被动关闭的后果就是会产生大量的CLOSE_WAIT连接。
幂等性Producer
Kafka保证消息不丢失的方式是Producer重试,比如实际上Broker已经接收到消息但是因为网络波动Producer没有接收到Broker的应答进行了重试。
重试是保障消息不丢失的必要手段,并没有什么问题,如果要实现不保存重复消息,可以让Broker进行去重。kafka在0.11.0.0版本引入Producer幂等性功能,设置props.put(“enable.idempotence”, ture),或 props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, true)即可。在Broker端多保存一些字段用于去重。
作用范围
只能保证某个主题的一个分区不出现重复消息,并且只能实现单会话上的幂等性,重启了Producer就保证不了了。
一个分区应该是怕影响效率。重启Producer保证不了应该是启动的时候kafka producer client生成的"client id"。
事务型Producer
设置事务型Producer:
- 开启enable.idempotence = true。
- 设置Producer端参数transactional.id。最好为其设置一个有意义的名字。
producer.initTransactions();
try {
producer.beginTransaction();
producer.send(record1);
producer.send(record2);
producer.commitTransaction();
} catch (KafkaException e) {
producer.abortTransaction();
}
实际上即使写入失败,Kafka也会把它们写入底层日志中,因此Consumer端读取事务型需要设置isolation.level=read_committed,当然非事务的消息也能读到。