kafka 代码示例
生成者API在不同版本间无较大变动;消费者(Consumer)提供了两套API
- 低版本(8.0版本及其以前)API
- 高版本(8.0版本后)API
两种API的优缺点:
高版本Consumer API 优点:
- 高级API写起来简单,易用。
不需要自行去管理offset,API已经封装好了offset这块的东西,会通过zookeeper自行管理
不需要管理分区,副本等情况,系统自动管理
消费者断线后会自动根据上次记录在zookeeper中的offset接着消费消息。
高版本Consumer API 缺点:
- 不能自行控制offset。
- 不能自行管理分区,副本,zk等相关信息。
低版本Consumer API 优点:
- 能够让开发者自己维护offset.想从哪里消费就从哪里消费
- 自行控制连接分区,对分区自定义负载均衡
- 对zookeeper的依赖性降低(如 offset 不一定要用zk来存储,可以存在缓存里或者内存中)
低版本Consumer API 缺点:
- 过于复杂,需要自行控制offset,连接哪个分区,找分区leader等。
使用者可以根据自身情对两种API况进行选取。
一:Producer
消息发送流程
Kafka的Producer发送消息采用的是异步发送的方式。在消息发送的过程中,涉及到了两个线程——main线程和Sender线程,以及一个线程共享变量——RecordAccumulator。main线程将消息发送给RecordAccumulator,Sender线程不断从RecordAccumulator中拉取消息发送到Kafka broker。
注意事项:参数说明
- batch.size:只有数据积累到batch.size之后,sender才会发送数据。
- linger.ms:如果数据迟迟未达到batch.size,sender等待linger.time之后就会发送数据。
代码示例
1. 导入依赖
<!-- kafka -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>0.11.0.0</version>
</dependency>
2. 代码部分
常用的类
- KafkaProducer :操作对象,用于数据发送。
- ProducerRecord :封装为ProducerRecord对象,进行传输。
- ProducerConfig :进行参数配置。
KafkaProducer 的构造方法
public KafkaProducer(Map<String, Object> configs) {
this(new ProducerConfig(configs), null, null);
}
public KafkaProducer(Map<String, Object> configs, Serializer<K> keySerializer, Serializer<V> valueSerializer) {
this(new ProducerConfig(ProducerConfig.addSerializerToConfig(configs, keySerializer, valueSerializer)),
keySerializer, valueSerializer);
}
public KafkaProducer(Properties properties) {
this(new ProducerConfig(properties), null, null);
}
private KafkaProducer(ProducerConfig config, Serializer<K> keySerializer, Serializer<V> valueSerializer) {
try {
log.trace("Starting the Kafka producer");
Map<String, Object> userProvidedConfigs = config.originals();
this.producerConfig = config;
......
}
上述源码可以看出,构造ProducerConfig来完成KafkaProducer的创建。而ProducerConfig的构造可以通过Map或者Properties来完成。本次代码示例使用Properties完成ProducerConfig的创建。
ProducerConfig 参数说明如下表
属性 | 描述 | 类型 | 默认值 |
---|---|---|---|
bootstrap.servers | 用于建立与kafka集群的连接,这个list仅仅影响用于初始化的hosts,来发现全部的servers。 格式:host1:port1,host2:port2,…,数量尽量不止一个,以防其中一个down了 |
list | |
acks | Server完成 producer request 前需要确认的数量。acks=0 时,producer不会等待确认,直接添加到socket等待发送;acks=1 时,等待leader写到local log就行;acks=all 或acks=-1 时,等待isr中所有副本确认(注意:确认都是 broker 接收到消息放入内存就直接返回确认,不是需要等待数据写入磁盘后才返回确认,这也是kafka快的原因) |
string | 1 |
buffer.memory | Producer可以用来缓存数据的内存大小。该值实际为RecordAccumulator类中的BufferPool,即Producer所管理的最大内存。 如果数据产生速度大于向broker发送的速度,producer会阻塞 max.block.ms ,超时则抛出异常 |
long | 33554432 |
compression.type | Producer用于压缩数据的压缩类型,取值:none, gzip, snappy, or lz4 |
string | none |
batch.size | Producer可以将发往同一个Partition的数据做成一个Produce Request发送请求,即Batch批处理,以减少请求次数,该值即为每次批处理的大小。 另外每个Request请求包含多个Batch,每个Batch对应一个Partition,且一个Request发送的目的Broker均为这些partition的leader副本。 若将该值设为0,则不会进行批处理 |
int | 16384 |
linger.ms | Producer默认会把两次发送时间间隔内收集到的所有Requests进行一次聚合然后再发送,以此提高吞吐量,而linger.ms则更进一步,这个参数为每次发送增加一些delay,以此来聚合更多的Message。 官网解释翻译:producer会将request传输之间到达的所有records聚合到一个批请求。通常这个值发生在欠负载情况下,record到达速度快于发送。但是在某些场景下,client即使在正常负载下也期望减少请求数量。这个设置就是如此,通过人工添加少量时延,而不是立马发送一个record,producer会等待所给的时延,以让其他records发送出去,这样就会被聚合在一起。这个类似于TCP的Nagle算法。该设置给了batch的时延上限:当我们获得一个partition的 batch.size 大小的records,就会立即发送出去,而不管该设置;但是如果对于这个partition没 |