1、Kafka 依赖
创建Maven工程,导入kafka依赖:
<!--kafka-->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>0.11.0.2</version>
</dependency>
2、Producer API:
package cn.xym.spark
import java.util.Properties
import org.apache.kafka.clients.producer.{KafkaProducer, ProducerRecord}
object Kafka {
def main(args: Array[String]): Unit = {
// 创建配置
val props = new Properties()
// 设置Kafka集群
props.put("bootstrap.servers", "chust01:9092")
// 设置ack
// 0: 不需要leader partition确认接收成功, 将消息发送到leader partition即可
// 1:需要等待leader partition确认接收成功
// -1(all): 需要等待leader partition以及ISR列表中的follower都确认接收成功
props.put("acks", "all")
// 设置key和value的序列化
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer")
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer")
// 创建一个Kafka的生产者
val producer = new KafkaProducer[String,String](props)
for (elem <- 1 to 100) {
// 发送消息 三个参数: ①topic, ②key, ③value
producer.send(new ProducerRecord[String,String]("test","1001","zhangsan"))
Thread.sleep(10000)
}
// 关闭资源
producer.close()
}
}
参数名称 | 说明 | 默认值 |
---|---|---|
bootstrap.servers | kafka集群的broker-list | |
acks | 确保生产者可靠性设置acks=0:不等待成功返回acks=1:等Leader写成功返回acks=all:等Leader和所有ISR中的Follower写成功返回,all也可以用-1代替 | -1 |
key.serializer | key的序列化器 | |
value.serializer | value的序列化器 | |
retries | 发送失败尝试重发次数 | 0 |
batch.size | 每个partition的未发送消息大小 | 16384 |
partitioner.class | 分区类,可以自定义分区类,实现partitioner接口 | 默认是哈希值%partitions |
max.block.ms | 最大阻塞时长 | 60000 |
3、Consumer API
package cn.xym.spark
import java.util.Properties
import org.apache.kafka.clients.consumer.KafkaConsumer
object KafkaConsumer{
def main(args: Array[String]): Unit = {
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.apache.kafka.clients.consumer.ConsumerRecords
import java.util
//创建一个配置
val props = new Properties()
//配置Kafka集群的ip和端口号
props.put("bootstrap.servers", "chust01:9092")
//设置消费者组的id,如果有多个相同id的消费者程序,那么他们将在一个组中
props.put("group.id", "testGroup1")
//开启自动提交,默认是开启
props.put("enable.auto.commit", "true") //默认值true
//默认每隔5000ms提交一次
props.put("auto.commit.interval.ms", "1000") //默认值5000
//key和value的序列化
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer")
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer")
//创建一个Consumer客户端
val consumer = new KafkaConsumer[String,String](props)
//consumer消费
val topics = new util.ArrayList[String]()
topics.add("test")
consumer.subscribe(topics)
//为了能够一直从Kafka中消费数据,使用while死循环
while (true){
//拉取数据,kafka推过来的一堆数据
val records = consumer.poll(1000)
//对这些数据转化为迭代器进行遍历输出
val iter = records.iterator()
while (iter.hasNext){
val next = iter.next()
println(s"partition = ${next.partition()},offset = ${next.offset()},value = ${next.key()},value = ${next.value()}")
}
}
}
}
4、Consumer Offset API 偏移
package cn.xym.spark
import java.util
import java.util.Properties
import org.apache.kafka.clients.consumer.{ConsumerRecord, ConsumerRecords, KafkaConsumer}
object KafkaConsumer2 {
def main(args: Array[String]): Unit = {
// 创建一个配置
val props = new Properties()
// 配置Kafka集群的ip和端口号
props.put("bootstrap.servers", "chust01:9092")
// 设置消费者组的id, 如果有多个相同id的消费者程序, 那么他们将在一个组当中
props.put("group.id", "testGroup1")
// 关闭自动提交[默认就是开启]
props.put("enable.auto.commit", "false")
// key和value的反序列化
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer")
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer")
// 创建一个Consumer客户端
val consumer = new KafkaConsumer[String, String](props)
// consumer消费
val topics = new util.ArrayList[String]()
topics.add("test")
// 订阅topic
consumer.subscribe(topics)
// 创建一个集合, 用来存放消息的个数
val buffer = new util.ArrayList[ConsumerRecord[String, String]]()
// 为了能够一直从Kafka中消费数据, 使用 while true 死循环
while (true) {
// 设置超时时间, 单位是毫秒, 返回一些条数据
val records: ConsumerRecords[String, String] = consumer.poll(1000)
// 对这些数据进行遍历输出
val iter: util.Iterator[ConsumerRecord[String, String]] = records.iterator()
while (iter.hasNext) {
val next: ConsumerRecord[String, String] = iter.next()
println(s"partition = ${next.partition()}, offset=${next.offset()}\nkey = ${next.key()}, value = ${next.value()}")
buffer.add(next)
}
if(buffer.size()>5){
// 手动提交offset有两种, 一种是同步阻塞方式, 一种是异步非阻塞方式
consumer.commitAsync()
// consumer.commitSync()
buffer.clear()
}
}
}
}