Spark Streaming自定义Receiver
一 背景
Spark社区为Spark Streaming提供了很多数据源接口,但是有些比较偏的数据源没有覆盖,由于公司技术栈选择,用了阿里云的MQ服务ONS,要做实时需求,要自己编写Receiver
二 技术实现
1.官网的例子已经比较详细,但是进入实践还需要慢慢调试,官方文档。
2.实现代码,由三部分组成,receiver,inputstream,util
3.receiver代码
import java.io.Serializable
import java.util.Properties import com.aliyun.openservices.ons.api._
import com.aliyun.openservices.ons.api.impl.ONSFactoryImpl
import org.apache.spark.internal.Logging
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming.receiver.Receiver class OnsReceiver(
cid: String,
accessKey: String,
secretKey: String,
addr: String,
topic: String,
tag: String,
func: Message => Array[Byte])
extends Receiver[Array[Byte]](StorageLevel.MEMORY_AND_DISK_2) with Serializable with Logging {
receiver => private var consumer: Consumer = null
private var workerThread: Thread = null override def onStart(): Unit = {
workerThread = new Thread(new Runnable {
override def run(): Unit = {
val properties = new Properties
properties.put(PropertyKeyConst.ConsumerId, cid)
properties.put(PropertyKeyConst.AccessKey, accessKey)
properties.put(PropertyKeyConst.SecretKey, secretKey)
properties.put(PropertyKeyConst.ONSAddr, addr)
properties.put(PropertyKeyConst.MessageModel, "CLUSTERING")
properties.put(PropertyKeyConst.ConsumeThreadNums, "50")
val onsFactoryImpl = new ONSFactoryImpl
consumer = onsFactoryImpl.createConsumer(properties)
consumer.subscribe(topic, tag, new MessageListener() {
override def consume(message: Message, context: ConsumeContext): Action = {
try {
receiver.store(func(message))
Action.CommitMessage
} catch {
case e: Throwable => e.printStackTrace()
Action.ReconsumeLater
}
}
})
consumer.start()
}
})
workerThread.setName(s"Aliyun ONS Receiver $streamId")
workerThread.setDaemon(true)
workerThread.start()
} override def onStop(): Unit = {
if (workerThread != null) {
if (consumer != null) {
consumer.shutdown()
} workerThread.join()
workerThread = null
logInfo(s"Stopped receiver for streamId $streamId")
}
}
}
input代码
import com.aliyun.openservices.ons.api.Message
import org.apache.spark.streaming.StreamingContext
import org.apache.spark.streaming.dstream.ReceiverInputDStream
import org.apache.spark.streaming.receiver.Receiver class OnsInputDStream(
@transient _ssc: StreamingContext,
cid: String,
topic: String,
tag: String,
accessKey: String,
secretKey: String,
addr:String,
func: Message => Array[Byte]
) extends ReceiverInputDStream[Array[Byte]](_ssc) { override def getReceiver(): Receiver[Array[Byte]] = {
new OnsReceiver(cid,accessKey,secretKey,addr,topic,tag,func)
} }
util代码
import com.aliyun.openservices.ons.api.Message
import org.apache.spark.annotation.Experimental
import org.apache.spark.streaming.StreamingContext
import org.apache.spark.streaming.dstream.{DStream, ReceiverInputDStream} object OnsUtils {
@Experimental
def createStream(
ssc: StreamingContext,
cid: String,
topic: String,
tag: String,
accessKey: String,
secretKey: String,
addr: String,
func: Message => Array[Byte]): ReceiverInputDStream[Array[Byte]] = {
new OnsInputDStream(ssc, cid, topic, tag, accessKey, secretKey, addr, func)
} @Experimental
def createStreams(
ssc: StreamingContext,
consumerIdTopicTags: Array[(String, String, String)],
accessKey: String,
secretKey: String,
addr: String,
func: Message => Array[Byte]): DStream[Array[Byte]] = {
val invalidTuples1 = consumerIdTopicTags.groupBy(e => (e._1, e._2)).filter(e => e._2.length > 1)
val invalidTuples2 = consumerIdTopicTags.map(e => (e._1, e._2)).groupBy(e => e._1).filter(e => e._2.length > 1)
if (invalidTuples1.size > 1 || invalidTuples2.size > 1) {
throw new RuntimeException("Inconsistent consumer subscription.")
} else {
ssc.union(consumerIdTopicTags.map({
case (consumerId, topic, tags) =>
createStream(ssc, consumerId, topic, tags, accessKey, secretKey, addr, func)
}))
}
} }
三 调用
val stream = (0 until 3).map(i => {
OnsUtils.createStream(ssc,
"CID",
"BI_CALL",
"call_log_ons",
config.getString("ons.access_key"),
config.getString("ons.sercet_key"),
config.getString("ons.ons_addr"),
func)
})
val unionStream = ssc.union(stream).foreachRDD(...)
stream可以决定设置多少个receiver,这个数量必须小于等于spark on yarn的num-executors,内存默认占用executors的内存的一半。
Spark Streaming自定义Receiver的更多相关文章
- spark Streaming的Receiver和Direct的优化对比
Direct 1.简化并行读取:如果要读取多个partition,不需要创建多个输入DStream然后对它们进行union操作.Spark会创建跟Kafka partition一样多的RDD part ...
- spark streaming 3: Receiver 到 submitJobSet
对于spark streaming来说,receiver是数据的源头.spark streaming的框架上,将receiver替换spark-core的以磁盘为数据源的做法,但是数据源(如监听某个 ...
- Spark Streaming自定义Receivers
自定义一个Receiver class SocketTextStreamReceiver(host: String, port: Int( extends NetworkReceiver[String ...
- 9. Spark Streaming技术内幕 : Receiver在Driver的精妙实现全生命周期彻底研究和思考
原创文章,转载请注明:转载自 听风居士博客(http://www.cnblogs.com/zhouyf/) Spark streaming 程序需要不断接收新数据,然后进行业务逻辑 ...
- 4. Spark Streaming解析
4.1 初始化StreamingContext import org.apache.spark._ import org.apache.spark.streaming._ val conf = new ...
- Spark Streaming Backpressure分析
1.为什么引入Backpressure 默认情况下,Spark Streaming通过Receiver以生产者生产数据的速率接收数据,计算过程中会出现batch processing time > ...
- Spark Streaming性能优化: 如何在生产环境下应对流数据峰值巨变
1.为什么引入Backpressure 默认情况下,Spark Streaming通过Receiver以生产者生产数据的速率接收数据,计算过程中会出现batch processing time > ...
- 【Streaming】30分钟概览Spark Streaming 实时计算
本文主要介绍四个问题: 什么是Spark Streaming实时计算? Spark实时计算原理流程是什么? Spark 2.X下一代实时计算框架Structured Streaming Spark S ...
- 第12课:Spark Streaming源码解读之Executor容错安全性
一.Spark Streaming 数据安全性的考虑: Spark Streaming不断的接收数据,并且不断的产生Job,不断的提交Job给集群运行.所以这就涉及到一个非常重要的问题数据安全性. S ...
随机推荐
- js中新增动态属性
var cc = 'hell' var mm = { [cc](){ alert(33) } } mm.hell() 使用的就是数组形式
- Ajax出现error常见情况(详细版)-火狐浏览器(Firefox)兼容性问题
作为一个程序员,遇到兼容性问题真的很苦恼,尤其是对我这种前端小菜鸡来说遇到了甚是凄惨.一般来说兼容性问题出现率Chrome < IE < Firefox (╯°Д°)╯︵┴┴ . 言归正 ...
- java常用基础(一)
Java常用基础(一) 原文写于2017-12-02 输入输出 //输入 Scanner in = new Scanner(new BufferedInputStream(System.in)); i ...
- 使用Jenkins部署.Net Core遇到的几个坑
搞过CI/CD的同学一定吃过不少苦头,或者说遇到不少坑,但是对自动化的执着住挡不了前进的步伐,如果你缺少了运维这一块知识,那么你的流水线总是不那么完美,本文记录的是自己躺过的坑,希望对你有所帮助. 一 ...
- 浅谈Linq查询
一.Var关键字 在学习Linq查询之前,我们先来学习var关键字的用法,看看微软官方的定义:从Visual C#3.0开始,在方法范围声明的变量可以具有隐式“类型” var.隐式类型的局部变量是强类 ...
- Codeforces Gym101518F:Dimensional Warp Drive(二分+高斯消元)
题目链接 题意 给出一个11元组A和11元组B,给出n个11元方程,每个方程有一个日期,要让A变成B,问最少需要日期多少才可以变. 思路 因为日期满足单调性,所以可以二分答案.判断的时候就是高斯消元套 ...
- k8s学习 - API
k8s学习 - API 之前对k8s并没有很深入的了解,最近想把手头一个项目全部放到k8s上,以方便部署,需要研究.这里记录一下自己研究过程中头脑中的理解. k8s 和 docker 首先,需要先理解 ...
- 哈工大计算机网络Week2-网络应用数据交换
目录 网络应用数据交换 P2P应用:原理与文件分发 纯P2P架构 文件分发:客户机/服务器 vs. P2P CS 为什么是这样的?不应该传送和发出难道是并行的??? P2P P2P文件分发典型例子:B ...
- zimg服务器图片数据迁移后,图片404异常的问题解决
由于zimg特殊的图片存储结构及图片命名规则,其迁移数据应该当相当简单的,仅把对应的存储图片数据的文件夹复制即可.往往简单的东西总会有一些成本在里面,下面是我简单的迁移测试过程中遇到的一些问题,仅供参 ...
- Spring Cloud Alibaba | Nacos配置管理
目录 Spring Cloud Alibaba | Nacos配置管理 1. pom.xml 项目依赖 2. 在 bootstrap.properties 中配置 Nacos server 的地址和应 ...