一.需求说明
SparkStreaming采集网页日志文件,计算网页的热度,根据网页热度排序取前10行,最后将网页ID和热度存入MySQL数据库
二.日志文件准备
说明:以原始数据 test.log为基础,用日志生成程序不断的
生成日志文件,以供SparkStraming采集和处理
网站热度计算规则:0.1*用户等级+0.9*访问次数+0.4*停留时间+是否点赞
原始数据文件 test.log。字段分隔符为 ","
10行
网页ID 用户等级 访问次数 停留时间 是否点赞(1为赞,-1表示踩,0表示中立)
041.html,7,5,0.9,-1
030.html,7,3,0.8,-1
042.html,5,4,0.2,0
032.html,6,2,0.4,1
042.html,5,1,0.8,0
045.html,6,4,0.7,1
047.html,8,3,0.5,-1
040.html,6,2,0.4,1
033.html,5,1,0.9,0
040.html,6,4,0.1,1
日志生成程序
import java.io.{File, PrintWriter}
import java.text.SimpleDateFormat
import java.util.Date
import scala.io.Source
object Simulator {
def main(args: Array[String]) {
var i=0
while (true)
{
// 日志文件所在路径
val filename="D:\\ChromeCoreDownloads\\test.log"
// 读取文件,并将每行数据转换成list集合
val lines = Source.fromFile(filename).getLines.toList
// 获取文件的总行数
val filerow = lines.length
// 创建一个文件,将生成的数据写入该文件中
val writer = new PrintWriter(new File("D:\\ChromeCoreDownloads\\sparkText\\streamingdata-"+i+".txt" ))
i=i+1
var j=0
while(j<100)
{
// 将lines集合中随机一行随机取出并存入新文件
writer.write(lines(index(filerow))+"\n")
// 输出这行内容
println(lines(index(filerow)))
j=j+1
}
writer.close()
// 程序等待 5 秒
Thread sleep 5000
}
}
// 随机获取索引值
def index(length: Int) = {
import java.util.Random
val rdm = new Random
rdm.nextInt(length)
}
}
三.创建对应的数据表
说明: id字段自增
,htmID对应网页ID
pageheat对应网页热度
create table streamText(
id int(8) NOT NULL auto_increment,
htmlID varchar(20),
pageheat varchar(20),
primary key(id));
四.SparkStreaming采集代码
import java.sql.{Connection, DriverManager}
import org.apache.spark.SparkConf
import org.apache.spark.streaming.dstream.DStream
import org.apache.spark.streaming.{Seconds, StreamingContext}
object StreamToMySQL {
def main(args: Array[String]): Unit = {
// 创建Streaming上下文对象
val conf = new SparkConf().setMaster( "local[*]" ).setAppName( "StreamToMySQL" )
val ssc: StreamingContext = new StreamingContext( conf, Seconds( 3 ) )
//使用ssc对象监控待采集目录
val file: DStream[String] = ssc.textFileStream( "D:\\ChromeCoreDownloads\\sparkText" )
//对文件中的每行数据进行分割
//使用公式计算网页的热度
val html: DStream[(String, Double)] = file.map { line =>
val fields = line.split( "," )
fields( 0 ) -> (0.1 * fields( 1 ).toInt + 0.9 * fields( 2 ).toInt + 0.4 * fields( 3 ).toDouble + fields( 4 )
.toInt)
}
//根据key计算相同网页热度的总和
//窗口大小为6秒,滑动周期是3秒
val htmlCount: DStream[(String, Double)] = html.reduceByKeyAndWindow( (v1: Double, v2: Double) => v1 + v2,
Seconds( 6 ), Seconds( 3 ) )
//根据每个网页的热度进行降序排序,取前 10 个
val htmlData: DStream[(String, Double)] = htmlCount.transform( rdd => {
val result = rdd.map( x => x._2 -> x._1 ).sortByKey( false ).map( x => x._2 -> x._1 ).take( 10 )
//将result转换成rdd返回,指定分区数为 1
ssc.sparkContext.makeRDD( result ).repartition( 1 )
}
)
// 将结果数据存入MySQL数据库
htmlData.foreachRDD { rdd =>
rdd.foreachPartition { partitionOfRecords =>
// 创建连接对象
val conn = connectMysql()
// 关闭自动提交 sql命令的提交由应用程序负责
conn.setAutoCommit( false )
val statement = conn.createStatement()
partitionOfRecords.foreach{ x =>
println(x._1,x._2)
val htmlID = x._1
val pageheat = x._2
statement.addBatch("insert into spark.streamText(htmlID,pageheat) values('"+htmlID+"','"+pageheat+"')")
}
// 将一批命令提交给数据库执行
statement.executeBatch()
conn.commit()
}
}
// 打印结果
htmlData.print()
//启动采集器
ssc.start()
//Driver等待采集器执行
ssc.awaitTermination()
}
//定义一个方法,用于连接数据库
def connectMysql(): Connection = {
val driver = "com.mysql.jdbc.Driver"
val url = "jdbc:mysql://192.168.220.25:3306/spark?&serverTimezone=GMT&useSSL=false"
val username = "root"
val pass = "mysql"
// 创建连接对象
Class.forName( driver )
val conn = DriverManager.getConnection( url, username, pass )
//将连接对象返回
conn
}
}
五.启动程序查看采集结果
1.启动日志生成程序开始生成日志
2.启动SparkStreaming程序开始采集处理日志
3.查看MySQL表中采集结果
开始生成日志
采集日志按热度排序并输出
查看数据表