【揭秘】Kafka发送端3大神秘模式,你了解吗?

Kafka发送端3大神秘模式 - 程序员古德

选择哪种发送模式取决于你的应用场景和需求。如果你需要极低的延迟和简单的代码实现,可以选择Fire-and-forget;如果你需要确保每条消息都被可靠地写入Kafka,并且能够处理错误,可以选择Synchronous send;如果你需要兼顾低延迟、高吞吐量和可靠性,可以选择Asynchronous send。

kafka发送端3种不同的发送模式,如下:

1、Fire-and-forget

只发送消息,不关心消息是否发送成功,本质上也是一种异步发送的方式,消息先存储在缓冲区中,达到设定条件后批量发送。

当然这是kafka吞吐量最高的一种方式,并配合参数acks=0,这样生产者不需要等待服务器的响应,以网络能支持的最大速度发送消息,但是也是消息最不可靠的一种方式,因为对于发送失败的消息没有做任何处理。

Fire-and-forget是最简单的发送模式,在这种模式下,生产者将消息发送到Kafka服务器后,不会等待任何来自服务器的响应,一旦消息被发送出去,生产者就会立即继续处理其他任务,不会关心消息是否成功写入Kafka。如下代码案例:

ProducerRecord<byte[],byte[]> record = new ProducerRecord<byte[],byte[]>("the-topic", key, value);
try {
  producer.send(record);
} catch (Exception e) {
  e.printStackTrace();
}

在发送消息之前有可能会发生异常,例如是序列化消息失败的SerializationException、缓冲区满的BufferExhaustedException、发送超时的TimeoutException或者发送的线程被中断的InterruptException,发送消息之后并没有异常处理。

这种方式有如下特点:

优点:

  • 低延迟:由于生产者不需要等待服务器的响应,因此可以实现非常低的延迟。
  • 高吞吐量:生产者可以快速地连续发送多条消息,不受服务器响应时间的限制。

缺点:

  • 不可靠:如果消息在传输过程中丢失,或者Kafka服务器未能成功接收消息,生产者将无法得知这一情况。
  • 无法处理失败:由于没有反馈机制,生产者无法对发送失败的消息进行重试或记录日志。

2、Synchronous send

同步发送,send()方法会返回Futrue对象,通过调用Futrue对象的get()方法,等待直到结果返回,根据返回的结果可以判断是否发送成功,如果业务要求消息必须是按顺序发送的,那么可以使用同步的方式,并且只能在一个partation上,结合参数设置retries的值让发送失败时重试,设置max_in_flight_requests_per_connection=1,可以控制生产者在收到服务器晌应之前只能发送1个消息,在消息发送成功后立刻flush,从而控制消息顺序发送。

在Synchronous send模式下,生产者发送消息后会阻塞并等待Kafka服务器的响应,只有当消息被成功写入Kafka,或者发生错误时,生产者才会继续执行后续操作。如下代码案例:

ProducerRecord<byte[],byte[]> record = new ProducerRecord<byte[],byte[]>("the-topic", key, value);
try {
  RecordMetadata metadata = producer.send(record).get();
} catch (Exception e) {
  e.printStackTrace();
}
producer.flush();
producer.close();

在调用send()方法后再调用get()方法等待结果返回。如果发送失败会抛出异常,如果发送成功会返回一个RecordMetadata对象,然后可以调用offset()方法获取该消息在当前分区的偏移量。

KafkaProducer有两种类型的异常,第一种是可以重试的Retriable,该类异常可以通过重新发送消息解决。例如是连接异常后重新连接、“no leader”异常后重新选取新的leader。KafkaProducer可以配置为遇到该类异常后自动重新发送消息直到超过重试次数。第二类是不可重试的,例如是“message size too large”(消息太大),该类异常会马上返回错误。

这种方式有如下特点:

优点:

  • 可靠性:生产者可以确保每条消息都被成功写入Kafka,或者得知发送失败的消息以便进行重试或记录日志。
  • 错误处理:生产者可以根据Kafka服务器的响应来处理错误(例如,网络问题或Kafka服务器内部错误)。

缺点:

  • 高延迟:由于需要等待Kafka服务器的响应,因此延迟较高。
  • 可能的吞吐量下降:生产者的吞吐量受限于Kafka服务器的响应时间。如果服务器响应缓慢,生产者的吞吐量也会降低。

3、Asynchronous send

异步发送,在调用send()方法的时候指定一个callback函数,当broker接收到返回的时候,该callback函数会被触发执行。

如果业务需要知道消息发送是否成功,并且对消息的顺序不关心,那么可以用异步+回调的方式来发送消息,配合参数retries=0,并将发送失败的消息记录到日志文件中;要使用callback函数,先要实现org.apache.kafka.clients.producer.Callback接口,该接口只有一个onCompletion方法,如果发送异常,onCompletion的参数Exception e会为非空。

Asynchronous send模式结合了Fire-and-forget和Synchronous send的特点。生产者发送消息后不会立即阻塞,而是继续执行其他任务。同时,生产者会异步地等待Kafka服务器的响应,并在收到响应后处理结果。

ProducerRecord<byte[],byte[]> record = new ProducerRecord<byte[],byte[]>("the-topic", key, value);
      producer.send(myRecord,
                   new Callback() {
                        public void onCompletion(RecordMetadata metadata, Exception e) {
                            if(e != null) {
                               e.printStackTrace();
                            } else {
                               System.out.println("The offset of the record we just sent is: " + metadata.offset());
                            }
                       }
                   });

这种方式有如下特点:

优点:

  • 低延迟和高吞吐量:生产者可以在等待服务器响应的同时继续发送其他消息,从而实现低延迟和高吞吐量。
  • 可靠性:与Fire-and-forget不同,生产者可以异步地得知消息的发送结果,并对失败的消息进行处理。
  • 灵活的错误处理:生产者可以自定义回调函数来处理Kafka服务器的响应,实现灵活的错误处理机制。

缺点:

  • 复杂性增加:与Fire-and-forget和Synchronous send相比,Asynchronous send需要更多的代码来处理异步操作和回调函数。
  • 潜在的并发问题:如果回调函数执行时间较长,可能会影响到生产者的性能和吞吐量。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员古德

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值