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日志没有配,不用理会,不会影响结果
往log.txt 文件写入内容
追加 8次 a到文件中,快速输入
写入成功
总结
只能一次写一个单词,如果需要请自行修改Spark代码。