SparkSQL结合SparkStreaming的使用

Flume+Kafka+SparkStreaming已经发展为一个比较成熟的实时日志收集与计算架构,利用Kafka,即可以支持将用于离线分析的数据流到HDFS,又可以同时支撑多个消费者实时消费数据,包括SparkStreaming。然而,在SparkStreaming程序中如果有复杂业务逻辑的统计,使用scala代码实现起来比较困难,也不易于别人理解。但如果在SparkSteaming中也使用SQL来做统计分析,是不是就简单的多呢?

本文介绍将SparkSQL与SparkStreaming结合起来,使用SQL完成实时的日志数据统计。SparkStreaming程序以yarn-cluster模式运行在YARN上,不单独部署Spark集群。

环境部署

Hadoop-2.3.0-cdh5.0.0(YARN)

spark-1.5.0-bin-hadoop2.3

kafka_2.10-0.8.2.1

另外,还编译了SparkStreaming用于读取Kafka数据的插件:

spark-streaming-kafka_2.10-1.5.0.jar

相关环境的部署本文不做介绍,请参考文章最后的相关阅读。

实时统计需求

以60秒为间隔,统计60秒内的pv,ip数,uv

最终结果包括:

时间点:pv:ips:uv

原始日志格式

2015-11-11T14:59:59|~|xxx|~|202.109.201.181|~|xxx|~|xxx|~|xxx|~|B5C96DCA0003DB546E7
2015-11-11T14:59:59|~|xxx|~|125.119.144.252|~|xxx|~|xxx|~|xxx|~|B1611D0E00003857808
2015-11-11T14:59:59|~|xxx|~|125.119.144.252|~|xxx|~|xxx|~|xxx|~|1555BD0100016F2E76F
2015-11-11T15:00:00|~|xxx|~|125.119.144.252|~|xxx|~|xxx|~|xxx|~|C0EA13670E0B942E70E
2015-11-11T15:00:00|~|xxx|~|125.119.144.252|~|xxx|~|xxx|~|xxx|~|C0EA13670E0B942E70E
2015-11-11T15:00:01|~|xxx|~|125.119.144.252|~|xxx|~|xxx|~|xxx|~|4E3512790001039FDB9

每条日志包含7个字段,分隔符为|~|,其中,第3列为ip,第7列为cookieid。假设原始日志已经由Flume流到Kafka中。

SparkStreaming程序代码

程序中使用下面的SQL语句完成对一个批次的数据统计:

SELECT date_format(current_timestamp(),'yyyy-MM-dd HH:mm:ss') AS time,
COUNT(1) AS pv,
COUNT(DISTINCT ip) AS ips,
COUNT(DISTINCT cookieid) as uv
FROM daplog

SparkStreaming程序代码:

package com.lxw.test

import scala.reflect.runtime.universe

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.SQLContext
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming.Seconds
import org.apache.spark.streaming.StreamingContext
import org.apache.spark.streaming.Time
import org.apache.spark.streaming.kafka.KafkaUtils
/**
* auth:lxw1234
* http://lxw1234.com
*/
object DapLogStreaming { def main (args : Array[String]) {
val sparkConf = new SparkConf().setMaster("yarn-cluster").setAppName("DapLogStreaming")
//每60秒一个批次
val ssc = new StreamingContext(sparkConf, Seconds(60))
//从Kafka中读取数据,topic为daplog,该topic包含两个分区
val kafkaStream = KafkaUtils.createStream(
ssc,
"bj11-65:2181", //Kafka集群使用的zookeeper
"group_spark_streaming", //该消费者使用的group.id
Map[String, Int]("daplog" -> 0,"daplog" -> 1), //日志在Kafka中的topic及其分区
StorageLevel.MEMORY_AND_DISK_SER)
.map(x => x._2.split("\\|~\\|", -1)) //日志以|~|为分隔符 kafkaStream.foreachRDD((rdd: RDD[Array[String]], time: Time) => {
val sqlContext = SQLContextSingleton.getInstance(rdd.sparkContext)
import sqlContext.implicits._
//构造case class: DapLog,提取日志中相应的字段
val logDataFrame = rdd.map(w => DapLog(w(0).substring(0, 10),w(2),w(6))).toDF()
//注册为tempTable
logDataFrame.registerTempTable("daplog")
//查询该批次的pv,ip数,uv
val logCountsDataFrame =
sqlContext.sql("select date_format(current_timestamp(),'yyyy-MM-dd HH:mm:ss') as time,count(1) as pv,count(distinct ip) as ips,count(distinct cookieid) as uv from daplog")
//打印查询结果
logCountsDataFrame.show()
}) ssc.start()
ssc.awaitTermination() } } case class DapLog(day:String, ip:String, cookieid:String) object SQLContextSingleton {
@transient private var instance: SQLContext = _
def getInstance(sparkContext: SparkContext): SQLContext = {
if (instance == null) {
instance = new SQLContext(sparkContext)
}
instance
}
}

示例中只是将实时统计的结果打印到标准输出,真实场景一般是将结果持久化到数据库中。

将该程序打包成DapLogStreaming.jar,上传至网关机。

运行SparkStreaming程序

进入$SPARK_HOME/bin执行下面的命令,将SparkStreaming程序提交到YARN:

./spark-submit \
--class com.lxw.test.DapLogStreaming \
--master yarn-cluster \
--executor-memory 2G \
--num-executors 6 \
--jars /home/liuxiaowen/kafka-clients-0.8.2.1.jar,/home/liuxiaowen/metrics-core-2.2.0.jar,/home/liuxiaowen/zkclient-0.3.jar,/home/liuxiaowen/spark-streaming-kafka_2.10-1.5.0.jar,/home/liuxiaowen/kafka_2.10-0.8.2.1.jar \
/home/liuxiaowen/DapLogStreaming.jar

注意:SparkStreaming及Kafka插件运行时候需要依赖相应的jar包。

查看运行结果

进入YARN ResourceManager的WEB界面,找到该程序对应的Application,点击ApplicationMaster的链接,进入SparkMaster界面:

每个批次(60秒),会生成一个Job。

点击TAB页”Streaming”,进入Streaming的监控页面:

在最下方,显示正在处理的批次和已经完成的批次,包括每个批次的events数量。

最后,最主要的,点击ApplicationMaster的logs链接,查看stdout标准输出:

已经按照SQL中统计的字段,打印出统计结果,每60秒一个批次打印一次。

注意事项

由于kafka_2.10-0.8.2.1是基于Scala2.10的,因此Spark、Spark的Kafka插件、SparkStreaming应用程序都需要使用Scala2.10,如果使用Scala2.11,运行时候会报出因Scala版本不一致而造成的错误,比如:

15/11/11 15:36:26 ERROR yarn.ApplicationMaster: User class threw exception: java.lang.NoSuchMethodError: scala.Predef$.ArrowAssoc(Ljava/lang/Object;)Ljava/lang/Object;
java.lang.NoSuchMethodError: scala.Predef$.ArrowAssoc(Ljava/lang/Object;)Ljava/lang/Object;
at org.apache.spark.streaming.kafka.KafkaUtils$.createStream(KafkaUtils.scala:59)
at com.lxw.test.DapLogStreaming$.main(DapLogStreaming.scala:23)
at com.lxw.test.DapLogStreaming.main(DapLogStreaming.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.spark.deploy.yarn.ApplicationMaster$$anon$2.run(ApplicationMaster.sc

sparkStreaming结合SparkSql实例的更多相关文章

  1. 071 SparkStreaming与SparkSQL集成

    1.说明 虽然DStream可以转换成RDD,但是如果比较复杂,可以考虑使用SparkSQL. 2.集成方式 Streaming和Core整合: transform或者foreachRDD方法 Cor ...

  2. 运行SparkStreaming的NetworkWordCount实例出错:Error connecting to localhost:9999 java.net.ConnectException: Connection refused 解决办法

    一.背景 首先按照Spark的官方文档来运行此实例,具体方法参见这里,当运行命令$ nc -lk 9999开启端口后,再运行命令$ ./bin/run-example streaming.Networ ...

  3. sparkStreaming结合sparkSql进行日志分析

    package testimport java.util.Propertiesimport org.apache.spark.SparkConfimport org.apache.spark.Spar ...

  4. spark-sql做ETL时遇到的两个问题

    项目中使用spark-sql来作ETL,遇到两个问题,记录一下. 问题1: spark-sql –master yarn –hiveconf load_date=`date –d ..`  -e 'i ...

  5. SequoiaDB 巨杉数据库

    传统单点数据库的容量瓶颈,仅仅是分布式数据库所解决的问题之一.更重要的是在未来微服务化应用开发以及云化平台的趋势下,应用不再以“烟囱式”的中间件加数据库模式进行构建,而是采用数千甚至上万的微服务程序构 ...

  6. 最近学习工作流 推荐一个activiti 的教程文档

    全文地址:http://www.mossle.com/docs/activiti/ Activiti 5.15 用户手册 Table of Contents 1. 简介 协议 下载 源码 必要的软件 ...

  7. flume+sparkStreaming实例 实时监控文件demo

    1,flume所在的节点不和spark同一个集群  v50和 10-15节点 flume在v50里面 flume-agent.conf spark是开的work节点,就是单点计算节点,不涉及到mast ...

  8. Spark入门实战系列--6.SparkSQL(下)--Spark实战应用

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .运行环境说明 1.1 硬软件环境 线程,主频2.2G,10G内存 l  虚拟软件:VMwa ...

  9. SparkStreaming入门及例子

    看书大概了解了下Streaming的原理,但是木有动过手啊...万事开头难啊,一个wordcount 2小时怎么都运行不出结果.是我太蠢了,好了言归正传. SparkStreaming是一个批处理的流 ...

随机推荐

  1. git clone慢的解决办法

    转自:http://www.kindemh.cn/ 转自Kindem的博客 问题 大家可能都遇到过从github使用git clone指令奇慢无比的问题,网上很多人说使用代理来加速git,但是这也不是 ...

  2. Codeforces 1169B Pairs

    题目链接:http://codeforces.com/contest/1169/problem/B 题意:给你 m 对数 ,问你能不能在 1 − n 之间找到俩个不相等的 x 和 y 使得 对于前面每 ...

  3. 5、cesium点击面高亮事件

    cesium点击面高亮事件 主要功能:比如你加载了json.geojson或者topojson的数据.加载出来后,分为很多个面,现在要实现点击一个面,这个面变颜色:再点击另一个面,另一个面高亮,之前的 ...

  4. Servlet.init() for servlet [springmvc] threw exception

    项目还没开始做,就碰到那么多问题.. 报错一:/oa/news/%E6%A0%8F%E7%9B%AE%E7%AE%A1%E7%90%86.jsp 1.一开始是jsp的页面名称为中文,改了 2.接着仍然 ...

  5. xshell6 远程连接时提示 WARNING! The remote SSH server rejected X11 forwarding request.

    1.输入命令 vi /etc/ssh/sshd_config ,修改配置文件 2.将UserLogin no 的注释解除   3.执行yum install -y xorg-x11-font xorg ...

  6. 关于阿里云 ETC服务器 端口开放问题

    今天整了个阿里云,为了开放一个端口 各种入出规则整了半天 最后连一个hello world都发不出来.. 最后的最后 才知道 开端口除了做入规则操作 还得调一下阿里的控制台 当你也买了个ECS不要像我 ...

  7. Ansible介绍

    第一章 ansible服务介绍 1.1 ansible批量管理服务概述 是基于python语言开发的自动化软件工具 是基于SSH远程管理服务实现远程主机批量管理 1.2 ansible批量管理服务意义 ...

  8. Mysql流程解析

    Mysql流程解析 流程图 流程图解析 客户端发送一条sql语句. 1.此时,mysql会检查sql语句,查看是否命中缓存,如果命中缓存,直接返回结果,不继续执行.没有命中则进入解析器. 2.解析器会 ...

  9. CSIC_716_20191204【网络编程 OSI 七层结构】

     软件开发架构 C/S架构: Client: 客户端 Server: 服务端 比如: 微信客户端.QQ客户端等... 优点: - 软件的使用稳定 - 节省网络资源 缺点: - 安装麻烦,用户体验差 - ...

  10. The past is just a story we tell ourselves.

    The past is just a story we tell ourselves.过去是我们说给自己听的故事.