Spark Streaming 读取Kafka数据源

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. 启动消费者

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值