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 ...
随机推荐
- Java 8 新特性-Stream更优雅的处理集合入门
Java 8 新特性之--Stream 一. 简单介绍 Stream是Java 8提出了的一种新的对集合对象功能的增强.它集合Lambda表达式,对集合提供了一些非常便利,高效的操作,使得代码具有非常 ...
- Python开发【第八篇】: 网络编程
内容概要 楔子 软件开发架构 网络基础 套接字(socket) 粘包 socketserver模块 一. 楔子 现在有两个python文件a.py和b.py,分别运行,这两个程序之间需要传递一个数据, ...
- python 基本数据类型之列表
#列表是可变类型,可以增删改查#字符串不可变类型,不能修改,只能生成新的值. #1.追加 # user_list = ['李泉','刘一','刘康','豆豆','小龙'] # user_list.ap ...
- python的数据类型之字符串(二)
字符串常见操作 如有字符串mystr = 'hello xiaose',以下是常见的操作 1.find 检测某个字符串是否包含在 mystr中,如果是返回开始的索引值,否则返回-1 格式:mystr. ...
- 源码阅读 - java.util.concurrent (三)ConcurrentHashMap
在java.util.concurrent包中提供了一个线程安全版本的Map类型数据结构:ConcurrentMap.本篇文章主要关注ConcurrentMap接口以及它的Hash版本的实现Concu ...
- Jmh测试JDK,CGLIB,JAVASSIST动态代理方式的性能
前言 JDK,CGLIB,JAVASSIST是常用的动态代理方式. JDK动态代理仅能对具有接口的类进行代理. CGLIB动态代理方式的目标类可以没有接口. Javassist是一个开源的分析.编辑和 ...
- 你必须了解的java内存管理机制(四)-垃圾回收
本文在个人技术博客不同步发布,详情可用力戳 亦可扫描屏幕右侧二维码关注个人公众号,公众号内有个人联系方式,等你来撩... 相关链接(注:文章讲解JVM以Hotspot虚拟机为例,jdk版本为1.8) ...
- linux服务器无telnet等测试工具,测试http+json服务连通性
1. 问题描述: 1.公司内部服务器需要通过http接口方式访问另一公司内部接口服务器. 2.申请信息安全开通访问权限,但是只能开通到服务器+端口号,例如:192.168.1:8080,无ping权限 ...
- C语言的指针移动怎么理解
C Primer pkus(第五版)中文版,老外写的还是很经典的,推荐给朋友们,购买地址:C primer plus 5版中文版购买 另外再推荐本书: 程序员面试宝典(第5版)第五版:程序员面试宝典( ...
- 【POJ - 1995】Raising Modulo Numbers(快速幂)
-->Raising Modulo Numbers Descriptions: 题目一大堆,真没什么用,大致题意 Z M H A1 B1 A2 B2 A3 B3 ......... AH ...