Spark实战小项目,Flume+Kafka+SparkStream+Mysql 实现单词计数

  • 请大佬多多指教!!!!!
  • 项目整体内容介绍
  • Flume配置文件编写
  • 开启Zookeeper(已配环境变量)
  • 开启Kafka服务器(已配环境变量)
  • 创建demo主题
  • 编写Spark代码
  • 我的maven依赖
  • 编写IDEA代码
  • 创建Mysql表
  • 到目前为止,我们的准备工作都已经完成了
  • 创建好Flume采集的目标文件
  • 启动之前编写的Flume demo.conf任务(已配)
  • 启动IDEA代码
  • 往log.txt 文件写入内容
  • 写入成功
  • 总结


请大佬多多指教!!!!!

项目整体内容介绍

1.此文章主要帮助朋友们理解Flume-Kafka-Spark-Mysql的简单流程教学。

2.Flume作用:通俗易懂来讲就是采集数据的

3.Kafka作用:用于暂时存放Flume采集的数据,等待Spark来拿数据分析

4.大概流程主要是,准备一个文件,Flume主要是监控这个文件,一旦文件有了变化,就把最新变化的数据采集过来,又交给Kafka保管着,此时,就等待Spark了,过一段时间spark就会去kafka这里看有没有数据,有就拿走,没有就下次来,当spark拿到数据之后,就分析存入数据库。OK

Flume配置文件编写

在linux任意位置创建文件 demo.conf 文件,修改三处地方:
1.监控的文件路径
2.zookeeper的 ip
3.主题的名字

a1.sources = r1
a1.sinks = k1
a1.channels = c1

a1.sources.r1.type = exec
#这里后面的绑定的是Flume监控的文件,log.txt文件可以提前建立好
a1.sources.r1.command = tail -F /home/torch/BigData/log.txt
a1.sinks.k1.hdfs.writeFormat = TEXT

a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink
#主题名字,这里为demo
a1.sinks.k1.kafka.topic=demo
#zookeeper的 ip
a1.sinks.k1.kafka.bootstrap.servers=localhost:9092
a1.sinks.k1.kafka.flumeBatchSize = 20
a1.sinks.k1.kafka.producer.acks = 1
a1.sinks.k1.kafka.producer.linger.ms = 1

a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

开启Zookeeper(已配环境变量)

zkServer.sh start

zookeeper的作用是辅助Kafka工作,对于这个项目,知道这些就行了

开启Kafka服务器(已配环境变量)

kafka-server-start.sh  /opt/module/kafka_2.11-2.3.1/config/server.properties

后面是kafka服务配置文件地址

创建demo主题

kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic demo

localhost为zookeeper的ip

编写Spark代码

我的maven依赖

<!-- Spark及Scala的版本号 -->
    <properties>
        <spark.version>2.1.0</spark.version>
        <scala.version>2.11</scala.version>
    </properties>

    <!-- Spark各个组件的依赖 -->
    <dependencies>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_${scala.version}</artifactId>
            <version>${spark.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-sql_${scala.version}</artifactId>
            <version>${spark.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-streaming_${scala.version}</artifactId>
            <version>${spark.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-streaming-kafka-0-8_${scala.version}</artifactId>
            <version>${spark.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-streaming-flume_${scala.version}</artifactId>
            <version>${spark.version}</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>

    </dependencies>

编写IDEA代码

import java.sql.{Connection, DriverManager, PreparedStatement}
import kafka.serializer.StringDecoder
import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.streaming.kafka.KafkaUtils

object worldcount {

  //Mysql链接方法
  private def getJdbcConnection(): Connection = {

    //设置驱动包
    Class.forName("com.mysql.jdbc.Driver").newInstance()
    //设置mysql地址
    val jdbcUrl = "jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8"
    //设置账户密码
    val conn = DriverManager.getConnection(jdbcUrl, "root", "root")
    conn
  }

  def main(args: Array[String]): Unit = {
    val sparkConf = new SparkConf().setAppName("worldcount").setMaster("local[2]")
    val streamingContext = new StreamingContext(sparkConf, Seconds(5))

    // 配置Kafka的broker地址
    val kafkaParams = Map[String,String]("metadata.broker.list"-> "localhost:9092")
    // 设置主题
    val topic = Set("demo")
    var ps: PreparedStatement = null
    val sql = "INSERT INTO worldcount(world,num) values(?,?)"
    // 利用KafakUtils创建DRStream
    val kafkaDStream = KafkaUtils.createDirectStream[String,String,StringDecoder,StringDecoder](streamingContext,kafkaParams,topic)
    val resultDStream = kafkaDStream.map(x => {
      val key = x._1
      val value = x._2
      (value,1)
    }).reduceByKey(_+_)
	resultDStream.print()
    resultDStream.map(x=>{
      ps = getJdbcConnection().prepareStatement(sql)
      //设置值
      ps.setString(1, x._1)
      ps.setInt(2, x._2)
      ps.executeUpdate()
      ps.close()
    }).print()
    // 开启
    streamingContext.start()
    // 等待结束
    streamingContext.awaitTermination()
  }
}

创建Mysql表

use mydb;

create table worldcount(world varchar(50),num int);

到目前为止,我们的准备工作都已经完成了

创建好Flume采集的目标文件

cd /home/torch/BigData/
vim log.txt

直接保存

:wq

启动之前编写的Flume demo.conf任务(已配)

flume-ng agent -n a1 -f /opt/module/flume/job/SparkDemo/demo.conf

-f 后面是demo.conf的路径

启动IDEA代码

如果下面出现如图,则是启动成功,如果你有很多红色和下面TIme:xxxxxxms 交替出现,则是log4j日志没有配,不用理会,不会影响结果

spark 实时数据接入处理 spark实时项目_sql

往log.txt 文件写入内容

追加 8次 a到文件中,快速输入

spark 实时数据接入处理 spark实时项目_大数据_02

写入成功

spark 实时数据接入处理 spark实时项目_kafka_03

总结

只能一次写一个单词,如果需要请自行修改Spark代码。