1. Kfaka介绍
Kfaka是一种高吞吐量的分布式发布订阅消息系统,用户通过Kafaka系统可以发布大量的消息,同时也能实时订阅消费消息;Kafka 可以同时满足在线实时处理和批量离线处理。在公司的大数据生态系统中,可以把Kafka作为数据交换枢纽,不同类型的分布式系统(关系数据库、NoSQL数据库、流处理系统、批处理系统等),可以统一接入到Kafka,实现和Hadoop各个组件之间的不同类型数据的实时高效交换。
1. Broker
Kafka集群包含一个或多个服务器,这种服务器被称为broker;
2. Topic
每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic。
3. Partition
是物理上的概念,每个Topic包含一个或多个Partition;
4. Producer
负责发布消息到Kafka broker;
5. Consumer
消息消费者,向Kafka broker读取消息的客户端;
6. Consumer Group
每个Consumer属于一个特定的Consumer Group。
2. Kfaka的安装与准备工作
安装教程参考: http://dblab.xmu.edu.cn/blog/1096-2/
假设安装目录为: /usr/local/kfaka
下载安装文件为Kafka_2.11-0.10.2.0.tgz,其中2.11是该Kafka所支持的Scala版本号,0.10.20是Kafka自身版本号。
1. 启动Zookeeper服务
./bin/zookeeper-server-start.sh config/zookerper.properties
2. 打开第二个终端,启动Kafka服务。不要关闭终端窗口。
./bin/kafka-server-start.sh config/sever.properties
3. Spark准备工作
Kafka和Flume等高级输入源,需要依赖独立的库(jar文件)
1. 下载jar包
对于Spark2.1.0版本,需要下载spark-streaming-kafka-0-8_2.11相关jar包,
下载地址为:http://mvnrepository.com/artifact/org.apache.spark/spark-streaming-kafka-0-8_2.11/2.1.0
2. jar包拷贝
1. 将jar文件复制到Spark目录的jars目录下;
2. 把Kafka安装目录的libs目录下的所有jar文件复制到 /usr/local/spark/jars/kafka 目录下。
4. 实例项目
生产者
import java.util.HashMap
import scala.util.Random
import org.apache.spark.streaming.kafka._
import org.apache.kafka.clients.producer.{ProducerConfig,ProducerRecord, kafkaProducer}
object KafkaWordProducer {
def main(args: Array[String]): Unit = {
if(args.length < 4){
System.err.println("Usage: KafkaWordProducer <metadataBrokerList>" +
"<topic> <messagesPerSec> <wordsPerMessage>")
System.exit(1)
}
val Array(brokers, topic, messagesPerSec, wordsPerMessage) = args
// zookeeper连接配置
val props = new HashMap[String, Object]()
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, brokers)
// 设置键、值序列化类型
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringSerializer")
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringSerializer")
val producer = new kafkaProducer[String, String](props)
// 发消息
while(true){
// 每秒产生多少条消息
(1 to messagesPerSec.toInt).foreach{ messageNum =>
val msg_str = (1 to wordsPerMessage.toInt) //每条消息包含多少个单词
.map(x => Random.nextInt(10).toString)
.mkString("")
print(str)
println()
val record = new ProducerRecord[String, String](topic, null, msg_str)
producer.send(record)
}
Thread.sleep(1000)
}
}
}
继续在当前目录下创建KafkaWordCount.scala(即消费者),对“生产者”的数据进行词频统计。
import org.apache.spark.sql.SparkSession
import org.apache.spark.streaming._
import org.apache.spark.streaming.kafka._
import org.apache.spark.streaming.kafka.KafkaUtils
object KafkaWordCount {
def main(args: Array[String]): Unit = {
StreamingExamples.setStreamingLogLevels()
val inputPath = "/user/zz/Desktop/checkpoint"
val spark = SparkSession
.builder()
.appName("wc")
.master("local")
.getOrCreate()
val ssc = new StreamingContext(spark.sparkContext, Seconds(10))
// 设置检查点,使用hdfs路径时(/user/hadoop/checkpoint),需要启动hadoop
ssc.checkpoint(inputPath)
val zkQuorum = "localhost:2181" // zookeeper服务器地址
val group = "1" // tipic所在的group,可以自己设定
val topics = "wordsender" // topics的名称
val numThreads = 1 // 每个topic的分区数
// 多个topic时,用“,”隔开;map中必须是“topic-分区数”的形式
val topicMap = topics.split(",")
.map((_, numThreads.toInt))
.toMap
val wc_rdd = KafkaUtils.createStream(ssc, zkQuorum, group, topicMap)
.map(_._2)
.flatMap(_.split(" "))
.map(x => (x,1))
// 第三个参数是窗口长度,第四个是步长
.reduceByKeyAndWindow(_+_, _-_, Minutes(2), Seconds(10), 2)
wc_rdd.print()
ssc.start()
ssc.awaitTermination()
spark.stop()
}
}
5. 编译运行
1. 启动生产者
2. 启动消费者