【大数据分析】Spark Streaming:Spark Streaming应用程序(一)

某些专业领域从实时数据分析中获利,比如流量监控、在线广告、股票市场交易等。这些案例需要可扩展的容错系统来摄入数据并进行分析,Spark Streaming具有用于从Hadoop兼容的文件系统(如HDFS和S3)和分布式系统(如Flume、Kafka和Twitter)读取数据并进行分析的能力。

Spark用于处理实时数据的方式是“小批量”,即:Spark Streaming获取一定时间段内的数据块并将其打包成RDD。

如上图所示,数据可以从各种外部系统进入Spark Streaming作业。这些包括文件系统和TCP/IP套接字连接,还包括其他分布式系统,如Kafka、Flume、Twitter和Amazon Kinesis,不同源使用不同的Spark Streaming接收器。Spark Streaming将传入的数据拆分为小批量RDD,一段时间后,Spark应用程序根据内置的逻辑对其进行处理。

创建流上下文

启动实时计算首先需要创建流的上下文,即创建一个StreamingContext实例。在Spark Shell中,使用SparkContext对象和Duration对象来实例化,该对象指定了Spark Streaming对于分割数据流数据和创建小批量RDD的时间间隔。假设需要使用5s的间隔:

import org.apache.spark._
import org.apache.spark.streaming._
val ssc = new StreamingContext(sc, Seconds(5))

此处可以使用Milliseconds和Minutes对象来指定持续时间,而不是用Seconds

StreamingContext构造函数重用了现有的SparkContext,如果给它一个Spark配置对象,Spark Streaming也可以启动一个新的SparkContext

创建离散流

作为案例,这里准备了包含50万行买卖订单记录的文件,记录随机生成,每行包含逗号分隔的元素如下。

-订单时间戳,格式yyyy-mm-dd hh:MM:ss。

-订单ID,连续递增,整数。

-客户端ID,从1-100范围内随机选取的整数。

-股票代码,从80个股票代码列表中选择。

-买入或卖出的股票数量,随机数从1到1000。

-购买或出售的价格,从1-100的随机数。

-字符B或S,该事件是否是买入或卖出的订单。

2016-03-22 20:25:28,1,80,EPE,710,51.00,B
2016-03-22 20:25:28,2,70,NFLX,158,8.00,B
2016-03-22 20:25:28,3,53,VALE,284,5.00,B
2016-03-22 20:25:28,4,14,SRPT,183,34.00,B
2016-03-22 20:25:28,5,62,BP,241,36.00,S
2016-03-22 20:25:28,6,52,MNKD,296,28.00,S
2016-03-22 20:25:28,7,65,CHK,791,60.00,B
2016-03-22 20:25:28,8,51,Z,620,21.00,B

......

StreamingContext的textFileStream方法可以监听目录,到达监听目录的数据文件会被处理,需要注意的是,textFileStream方法不会处理文件夹中已存在的文件,也不会对添加到文件中的数据做出反应。

val ssc = new StreamingContext(sc, Seconds(5))
val filestream = ssc.textFileStream("/home/spark/input")

上面代码得到了一个fileDstream对象是DStream类的一个实例。DStream(离散流)是Spark Streaming中的基本抽象,表示从输入流周期性创建的RDD序列。

使用离散流

有了DStream对象之后,需要使用它来计算每秒销售和购买订单的数量。

首先将每行转换成更易于管理的内容,如case class,比如需要保存订单数据时

import java.sql.Timestamp
case class Order(time: java.sql.Timestamp, orderId:Long, clientId:Long, symbol:String, amount:Int, price:Double, buy:Boolean)

然后解析filestream DStream的行,从而获取包含Order对象的新DStream,这个过程可以使用flatMap。

import java.text.SimpleDateFormat
val orders = filestream.flatMap(line => {
    val dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss")
    val s = line.split(",")
    try {
        assert(s(6) == "B" || s(6) == "S")
        List(Order(new Timestamp(dateFormat.parse(s(0)).getTime()), s(1).toLong, s(2).toLong, s(3), s(4).toInt, s(5).toDouble, s(6) == "B"))
    }
    catch {
        case e : Throwable => println("Wrong line format ("+e+"): "+line)
        List()
    }
})

接着使用PairDStreamFunction来计算每秒买卖订单的数量。与RDD类似,如果RDD包含双元素元组,则它们将隐式转换为PairRDDFunction,如果DStream包含双元素元组,则它会自动转换为PairDStreamFunction对象。所以DStream对象也可以使用诸如combineByKey,reduceByKey和flatMapValue这样的一些函数。

计算每种订单类型的发生次数

val numPerType = orders.map(o => (o.buy, 1L)).reduceByKey((c1, c2) => c1+c2)

保存结果

可以使用DStream的saveAsTextFiles方法保存结果。它需要两个参数,保存路径和文件后缀。例如每5s会创建一个新的目录。这些目录中的每一个都包含RDD中每个分区的一个文件,名为part-xxxx(xxxx是分区的编号)

numPerType.repartition(1).saveAsTextFiles("/home/spark/output", "txt")

启动和停止流计算

可以使用以下代码启动或停止流计算和流上下文

ssc.start()
ssc.stop(false)

流上下文负责评估创建的DStream,启动接收器,并开始运行DStream代表的程序,注意不能在同一个JVM中启动多个StreamingContext。

false表示在停止流上下文的时候不停止Spark上下文。用户不能重新启动已经停止的流上下文,但可以使用现有的Spark上下文来创建新的流上下文。

启动中的Spark Streaming应用程序并没有可以处理的数据,除非发送数据到Spark Streaming中,假设可以使用shell脚本文件splitAndSend.sh发送数据到监听的目录

if [ -z "$1" ]; then
        echo "Missing output folder name"
        exit 1
fi

split -l 10000 --additional-suffix=.ordtmp orders.txt orders

for f in `ls *.ordtmp`; do
        if [ "$2" == "local" ]; then
                mv $f $1
        else
                hdfs dfs -copyFromLocal $f $1
                rm -f $f
        fi
        sleep 3
done

执行命令如下

./splitAndSend.sh /home/spark/input local

计算完成后如果查看文件夹,则会发现每个文件夹中都有两个文件,命名为part-00000和__SUCCESS,part-00000包含计算的计数,__SUCCESS意味着写入成功完成。当需要快速读取这些文件时,可以使用下面的代码

val allCounts = sc.textFile("/home/spark/output*.txt")

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值