带你认识三种kafka消息发送模式
摘要:在kafka-0.8.2之后,producer不再区分同步(sync)和异步方式(async),所有的请求以异步方式发送,这样提升了客户端效率。
本文分享自华为云社区《kafka消息发送模式》,作者:dayu_dls。
在kafka-0.8.2之后,producer不再区分同步(sync)和异步方式(async),所有的请求以异步方式发送,这样提升了客户端效率。producer请求会返回一个应答对象,包括偏移量或者错误信。这种异步方地批量的发送消息到kafka broker节点,因而可以减少server端资源的开销。新的producer和所有的服务器网络通信都是异步地,在ack=-1模式下需要等待所有的replica副本完成复制时,可以大幅减少等待时间。
为生产者设置属性
1. bootstrap.servers: 该属性指定broker 的地址清单,地址的格式为host:po 忱。清单里不需要包含所有的broker 地址,生产者会给定的broker 里查找到其他broker 的信息。不过建议至少要提供两个broker 的信息, 一且其中一个若机,生产者仍然能够连接到集群上。
2. key.serializer: broker 希望接收到的消息的键和值都是字节数组。生产者接口允许使用参数化类型,因此可以把Java 对象作为键和值发送给broker 。这样的代码具有良好的可读性,不过生产者需要知道如何把这些Java 对象转换成字节数组。key. serializer必须被设置为一个实现了org.apache.kafka.common.serialization.StringSerializer接口的类,生产者会使用这个类把键对象序列化成字节数组。Kafka 客户端默认提供了ByteArraySerializer(这个只做很少的事情)、StringSerializer和IntegeSerializer,因此,如果你只使用常见的几种Java 对象类型,那么就没必要实现自己的序列化器。要注意, key.serializer是必须设置的,就算你打算只发送值内容。
3. value.serializer: 与key.serializer一样,value.serializer指定的类会将值序列化。如果键和值都是字符串,可以使用与key.serializer一样的序列化器。如果键是整数类型而值是字符串,那么需要使用不同的序列化器。
kafka发送端3种不同的发送模式
1、Fire-and-forget
只发送消息,不关心消息是否发送成功。本质上也是一种异步发送的方式,消息先存储在缓冲区中,达到设定条件后批量发送。当然这是kafka吞吐量最高的一种方式,并配合参数acks=0,这样生产者不需要等待服务器的响应,以网络能支持的最大速度发送消息。但是也是消息最不可靠的一种方式,因为对于发送失败的消息没有做任何处理。
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。发送消息之后并没有异常处理。
2、Synchronous send
同步发送,send()方法会返回Futrue对象,通过调用Futrue对象的get()方法,等待直到结果返回,根据返回的结果可以判断是否发送成功。如果业务要求消息必须是按顺序发送的,那么可以使用同步的方式,并且只能在一个partation上,结合参数设置retries的值让发送失败时重试,设置max_in_flight_requests_per_connection=1,可以控制生产者在收到服务器晌应之前只能发送1个消息,在消息发送成功后立刻flush,从而控制消息顺序发送。
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”(消息太大),该类异常会马上返回错误。
3、Asynchronous send
异步发送,在调用send()方法的时候指定一个callback函数,当broker接收到返回的时候,该callback函数会被触发执行。如果业务需要知道消息发送是否成功,并且对消息的顺序不关心,那么可以用异步+回调的方式来发送消息,配合参数retries=0,并将发送失败的消息记录到日志文件中;要使用callback函数,先要实现org.apache.kafka.clients.producer.Callback接口,该接口只有一个onCompletion方法。如果发送异常,onCompletion的参数Exception e会为非空。
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());
}
}
});
异步发送相关参数
异步发送时,kafka会先把消息存储在缓冲池中,当到达设定条件触发缓冲池消息发送。
(1)消息缓存达到batch.size;
(2)距离上一次消息发送时间间隔linger.ms;
(3)调用flush()方法,会立刻触发发送,并阻塞到当前缓冲区发送完毕;
(4)调用close(),触发发送,完毕后关闭。
buffer.memory
此配置设置生产者可用于缓冲等待发送给brokers消息的总内存字节数,默认为33554432=32MB。如果消息发送到缓存区的速度比发送到broker的速度快,那么生产者会被阻塞(根据max.block.ms配置的时间,默认为60000ms=1分钟,在0.9.0.0版本之前使用block.on.buffer.full配置),之后会抛出异常。
compression.type
生产者对生成的所有数据使用的压缩类型,默认值是none(即不压缩),有效值为none,gzip,snappy或lz4。Snappy压缩技术是Google开发的,它可以在提供较好的压缩比的同时,减少对CPU的使用率并保证好的性能,所以建议在同时考虑性能和带宽的情况下使用。Gzip压缩技术通常会使用更多的CPU和时间,但会产生更好的压缩比,所以建议在网络带宽更受限制的情况下使用。通过启用压缩功能,可以减少网络利用率和存储空间,这往往是向Kafka发送消息的瓶颈。
retries
默认值为0,当设置为大于零的值,客户端会重新发送任何发送失败的消息。注意,此重试与客户端收到错误时重新发送消息是没有区别的。在配置max.in.flight.requests.per.connection不等于1的情况下,允许重试可能会改变消息的顺序,因为如果两个批次的消息被发送到同一个分区,第一批消息发送失败但第二批成功,而第一批消息会被重新发送,则第二批消息会先被写入。注意此参数可能会改变消息的顺序性。
batch.size
当多个消息被发送到同一个分区时,生产者会把它们一起处理。此配置设置用于每批处理使用的内存字节数,默认为16384=16KB。当使用的内存满的时候,生产者会发送当前批次的所有消息。但是,这并不意味着生产者会一直等待使用的内存变满,根据下面linger.ms配置的时间也会触发消息发送。设置较小的值会增加发送的频率,从而可能会减少吞吐量;设置较大的值会使用较多的内存,设置为0会关闭批处理的功能。
linger.ms
此配置设置在发送当前批次消息之前等待新消息的时间量,默认值为0。KafkaProducer会在当前批次使用的内存已满或等待时间到达linger.ms配置时间的时候发送消息。当linger.ms>0时,延时性会增加,但会提高吞吐量,因为会减少消息发送频率。
client.id
用于标识发送消息的客户端,通常用于日志和性能指标以及配额。
max.in.flight.requests.per.connection
此配置设置客户端在单个连接上能够发送的未确认请求的最大数量,默认为5,超过此数量会造成阻塞。设置大的值可以提高吞吐量但会增加内存使用,但是需要注意的是,当设置值大于1而且发送失败时,如果启用了重试配置,有可能会改变消息的顺序。设置为1时,即使重新发送消息,也可以保证发送的顺序和写入的顺序一致。
request.timeout.ms
此配置设置客户端等待请求响应的最长时间,默认为30000ms=30秒,如果在这个时间内没有收到响应,客户端将重发请求,如果超过重试次数将抛异常。此配置应该比replica.lag.time.max.ms(broker配置,默认10秒)大,以减少由于生产者不必要的重试造成消息重复的可能性。
max.block.ms
当发送缓冲区已满或者元数据不可用时,生产者调用send()和partitionsFor()方法会被阻塞,默认阻塞时间为60000ms=1分钟。由于使用用户自定义的序列化器和分区器造成的阻塞将不会计入此时间。
max.request.size
此配置设置生产者在单个请求中能够发送的最大字节数,默认为1048576字节=1MB。例如,你可以发送单个大小为1MB的消息或者1000个大小为1KB的消息。注意,broker也有接收消息的大小限制,使用的配置是message.max.bytes=1000012字节(好奇怪的数字,约等于1MB)。
receive.buffer.bytes和send.buffer.bytes
receive.buffer.bytes:读取数据时使用的TCP接收缓冲区(SO_RCVBUF)的大小,默认值为32768字节=32KB。如果设置为-1,则将使用操作系统的默认值。
send.buffer.bytes:发送数据时使用的TCP发送缓冲区(SO_SNDBUF)的大小,默认值为131072字节=128KB。如果设置为-1,则将使用操作系统的默认值。
带你认识三种kafka消息发送模式的更多相关文章
- 源码分析 Kafka 消息发送流程(文末附流程图)
温馨提示:本文基于 Kafka 2.2.1 版本.本文主要是以源码的手段一步一步探究消息发送流程,如果对源码不感兴趣,可以直接跳到文末查看消息发送流程图与消息发送本地缓存存储结构. 从上文 初识 Ka ...
- 源码分析 Kafka 消息发送流程
Futuresend(ProducerRecord<K, V> record) Futuresend(ProducerRecord<K, V> record, Callback ...
- RabbitMQ系列(八)--顺序消费模式和迅速消息发送模式
MQ使用过程中,有些业务场景需要我们保证顺序消费,而如果一个Producer,一个Queue,多个Consumer的情况下是无法保证顺序的 举例: 1.业务上产生三条消息,分别是对数据的增加.修改.删 ...
- Objective-C(十九、通知-消息发送模式之中的一个)——iOS开发基础
结合之前的学习笔记以及參考<Objective-C编程全解(第三版)>,对Objective-C知识点进行梳理总结. 知识点一直在变.仅仅是作为參考.以苹果官方文档为准~ 十九.通知-消息 ...
- LVS负载均衡常用的工作模式有NAT、DR、和TUN三种,其中DR模式性能最为优越,使用最为广泛。
一.安装LVS LVS的编译安装参考本站文章:http://www.linuxe.cn/post-192.html,对于LVS这种功能性软件,在生产中用yum安装也是没有问题的. 1 yum inst ...
- Tomcat Connector的三种不同的运行模式
Tomcat Connector的三种不同的运行模式性能相差很大,有人测试过的结果如下: 这三种模式的不同之处如下: BIO: 一个线程处理一个请求.缺点:并发量高时,线程数较多,浪费资源. Tomc ...
- SpringCloud(六) - RabbitMQ安装,三种消息发送模式,消息发送确认,消息消费确认(自动,手动)
1.安装erlang语言环境 1.1 创建 erlang安装目录 mkdir erlang 1.2 上传解压压缩包 上传到: /root/ 解压缩# tar -zxvf otp_src_22.0.ta ...
- 带你用三种不同的工具体验AI作诗
摘要:本实验基于华为云API Arts和API Explorer,向用户介绍诗歌生成API,指导用户使用华为云工具,体验AI作诗的过程. 本文分享自华为云社区<AI语言能力体验:通过三种不同的工 ...
- RocketMQ源码 — 三、 Producer消息发送过程
Producer 消息发送 producer start producer启动过程如下图 public void start(final boolean startFactory) throws MQ ...
- C2C,B2C,F2C三种电商运营模式的比较
第三方模式(C2C) 销售商模式(B2C) 生产商模式(F2C) 概念及简介 第三方平台提供商模式是电子商务的最原始也是最自然的形式.这种模式一般都是由信息技术开发商负责建立平台,利用平台扩展电子 ...
随机推荐
- [Python] 利用python的第三方库xlrd和xlwt来处理excel数据
今天在处理excel表格的时候,有一个需要提取表格中部分数据的操作.如果人工操作的话,有将近几千行,这样重复操作劳民伤财. 所以python就派上用场了. 简单介绍一下我要处理的问题,在excel一列 ...
- CF1401B [Ternary Sequence]
Problem 题目简述 两个序列 \(A, B\).这两个序列都是由 \(0,1,2\) 这三个数构成. \(x_1,y_1,z_1\) 和 \(x_2,y_2,z_2\) 分别代表 \(A\) 序 ...
- TerraMoursGPT V1.0 开发总结
TerraMoursGPT V1.0 开发总结 TerraMoursGPT V1.0 是之前gpt项目基于TerraMours后端框架的重构,实现用户登陆和基于SK的多语言模型聊天.基于chatgpt ...
- JVM-Java虚拟机是怎么实现synchronized的?
1. JVM的锁优化 今天我介绍了 Java 虚拟机中 synchronized 关键字的实现,按照代价由高至低可分为重量级锁.轻量级锁和偏向锁三种. 重量级锁会阻塞.唤醒请求加锁的线程.它针对的是多 ...
- cookie、session、web storage
cookie与session的区别 首先,使用cookie和session的目的都是为了跟踪记录用户状态,因为http协议是无状态的协议,而某些场景服务端需要记录用户的状态,如购物车,需要来识别具体的 ...
- AtCoder Beginner Contest 329 (ABC329)
A. Spread 不说了,代码. B. Next 不说了,代码. C. Count xxx Description 给定一个长度为 \(N\) 的字符串 \(S\),求 \(S\) 中非空连续,并且 ...
- React 应用构建(环境)
可以少去理解一些不必要的概念,而多去思考为什么会有这样的东西,它解决了什么问题,或者它的运行机制是什么? 一. 环境搭建 工作编辑器:Visual Studio Code. Javascript 解析 ...
- Typora的安装与使用教程
一.安装 1.下载 下载地址:Typora 官方中文站 二.安装 1.无脑下一步即可. 三.使用教程 1.Typora系统设置 一般导出使用PDF文件比较好,性价比比较高. 2.其他设置 以下所有设置 ...
- 国内 AI 成图第一案!你来你会怎么判?
我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K 哥特设了"K哥爬虫普法"专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识, ...
- .NET使用分布式网络爬虫框架DotnetSpider快速开发爬虫功能
前言 前段时间有同学在微信群里提问,要使用.NET开发一个简单的爬虫功能但是没有做过无从下手.今天给大家推荐一个轻量.灵活.高性能.跨平台的分布式网络爬虫框架(可以帮助 .NET 工程师快速的完成爬虫 ...