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 ...
随机推荐
- 移动IM开发指南2:心跳指令详解
<移动IM开发指南>系列文章将会介绍一个IM APP的方方面面,包括技术选型.登陆优化等.此外,本文作者会结合他在网易云信多年iOS IM SDK开发的经验,深度分析实际开发中的各种常见问 ...
- vuex分模块3
nuxt 踩坑之 -- Vuex状态树的模块方式使用 原创 2017年12月20日 11:24:14 标签: vue / nuxt / vuex / 模块化 / 状态管理 874 初次看到这个模块方式 ...
- 【转+存】JVM指令集
jvm指令集: 转载地址:https://www.cnblogs.com/yaoyinglong/p/4300447.html 一.未归类系列A 此系列暂未归类. 指令码 助记符 ...
- zphp源码分析(一)
zphp是一款轻量级的php服务端框架,是swoole官方开发的.可以用来开发web应用和网络服务. 安装: 可以通过composer安装, { "require": { &quo ...
- 为什么很多IT公司不喜欢进过培训机构的人呢
这几天在知乎看到一个问题“为什么很多IT公司不喜欢进过培训机构的人呢?” 身为IT培训师,这样的问题必然会引起我的关注, 花时间看了各路人士的回答, 我了个去,尽是对培训机构排山倒海的谩骂声, 负面评 ...
- PATA 1071 Speech Patterns.
#include <bits/stdc++.h> using namespace std; bool check(char c)//检查是否为字母或数字 { if(c>='A'&am ...
- chromedriver配置
需要先安装chrome浏览器,添加chrome源 sudo vim /etc/yum.repos.d/google-chrome.repo 添加以下内容 [google-chrome] name=go ...
- esxi开启SSH
- Codeforces 1133E - K Balanced Teams - [DP]
题目链接:https://codeforces.com/contest/1133/problem/C 题意: 给出 $n$ 个数,选取其中若干个数分别组成 $k$ 组,要求每组内最大值与最小值的差值不 ...
- Net Core 2.1 日志记录框架NLog+Mysql配置
NLog是什么? 这里还是简单介绍一下吧,为了让小白也知道.NLog是一个灵活的免费日志记录平台,适用于各种.NET平台,包括.NET Core.NLog可以通过简单地配置就可以可以很方便的写入多个日 ...