Spark Streaming 的玫瑰与刺

前言

说人话:其实就是讲Spark Streaming 的好处与坑。好处主要从一些大的方面讲,坑则是从实际场景中遇到的一些小细节描述。

玫瑰篇

玫瑰篇主要是说Spark Streaming的优势点。

玫瑰之代码复用

这主要得益于Spark的设计,以及平台的全面性。你写的流处理的代码可以很方便的适用于Spark平台上的批处理,交互式处理。因为他们本身都是基于RDD模型的,并且Spark Streaming的设计者也做了比较好的封装和兼容。所以我说RDD是个很强大的框,能把各种场景都给框住,这就是高度抽象和思考后的结果。

玫瑰之机器学习

如果你使用Spark MLib 做模型训练。恭喜你,首先是很多算法已经支持Spark Streaming,也就是流式计算 ,其次,离线计算好的模型也是可以在Spark Streaming中很自然的load进来,从而进行预测等操作。

玫瑰之SQL支持

Spark Streaming 里天然就可以使用 sql/dataframe/datasets 等。而且时间窗口的使用可以极大扩展这种使用场景,譬如各种系统预警等。类似Storm则需要额外的开发与支持。

玫瑰之吞吐和实时的有效控制

Spark Streaming 可以很好的控制实时的程度(小时,分钟,秒)。极端情况可以设置到毫秒。

玫瑰之概述

Spark Streaming 可以很好的和Spark其他组件进行交互,获取其支持。同时得益于Spark 生态圈的快速发展,亦能从中受益。

 

刺篇

刺篇就是描述Spark Streaming 的一些问题,做选型前关注这些问题可以有效的降低使用风险。

checkpoint 之刺

checkpoint 是个很好的恢复机制。但是方案比较粗暴,直接通过序列化的机制写入到文件系统,导致代码变更和配置变更无法生效。实际场景是升级往往比系统崩溃的频率高太多。但是升级需要能够无缝的衔接上一次的偏移量。所以spark streaming在无法容忍数据有丢失的情况下,你需要自己记录偏移量,然后从上一次进行恢复。

我们目前是重写了相关的代码,每次记录偏移量,不过只有在升级的时候才会读取自己记录的偏移量,其他情况都是依然采用checkpoint机制。

Kafka 之刺

这个和Spark Streaming相关,也不太相关。说相关是因为Spark 对很多异常处理比较简单。很多是和Kafka配置相关的。我举个例子:

如果消息体太大了,超过 fetch.message.max.bytes=1m,那么Spark Streaming会直接抛出OffsetOutOfRangeException异常,然后停止服务。

对应的错误会从这行代码抛出:

if (!iter.hasNext) {
 assert(requestOffset == part.untilOffset, errRanOutBeforeEnd(part))
 finished = true
 null.asInstanceOf[R]
}

其实就是消费的完成后 实际的消费数据量和预先估计的量不一致。

你在日志中看到的信息其实是这个代码答应出来的:

private def errRanOutBeforeEnd(part: KafkaRDDPartition): String =
 s"Ran out of messages before reaching ending offset ${part.untilOffset} " +
 s"for topic ${part.topic} partition ${part.partition} start ${part.fromOffset}." +    " This should not happen, and indicates that messages may have been lost"

解决办法自然是把 fetch.message.max.bytes 设置大些。

如果你使用Spark Streaming去追数据,从头开始消费kafka,而Kafka因为某种原因,老数据快速的被清理掉,也会引发OffsetOutOfRangeException错误。并且使得Spark Streaming程序异常的终止。

解决办法是事先记录kafka偏移量和时间的关系(可以隔几秒记录一次),然后根据时间找到一个较大的偏移量开始消费。

或者你根据目前Kafka新增数据的消费速度,给smallest获取到的偏移量再加一个较大的值,避免出现Spark Streaming 在fetch的时候数据不存在的情况。

textFileStream

其实使用textFileStream 的人应该也不少。因为可以很方便的监控HDFS上某个文件夹下的文件,并且进行计算。这里我们遇到的一个问题是,如果底层比如是压缩文件,遇到有顺坏的文件,你是跳不过去的,直接会让Spark Streaming 异常退出。 官方并没有提供合适的方式让你跳过损坏的文件。我们目前是通过重写FileInputDStream 等相关类来修正该问题。

内存之刺

Shuffle (尤其是每个周期数据量很大的情况)是Spark Streaming 不可避免的疼痛。譬如,与Kafka的集成, Kafka的分区数决定了你的并行度(我们假设你使用Direct Approach的模式集成)。你为了获得更大的并行度,则需要进行一次repatition。 为了能够避免Shuffle,并且提高Spark Streaming处理的并行度,我们重写了 DirectKafkaInputDStream,KafkaRDD,KafkaUtils等类,实现可以按Kafka 分区按倍数扩大并行度。

我们期望官方能够实现将一个Kafka的partition 映射为多个Spark 的partition,避免数据的多次移动。

再次,如果单个Executor 并行度过大,可能也会导致对内存压力增大。在使用Spark Streaming的过程中,我们多次遇到Executor Lost 相关的问题(譬如 shuffle fetch 失败,Task失败重试等),目前比较有效的方式是:

  1. 提高Executor 数目
  2. 减少单个Executor的 CPU 核数

为了保证处理的效率,请保证CPU总核数保持不变。

监控之刺

Spark Streaming 的UI 上的Executors Tab缺少一个最大的监控,就是Worker内存GC详情。虽然我们可以将这些信息导入到 第三方监控中,然而终究是不如在 Spark UI上展现更加方便。 为此我们也将该功能列入研发计划。

总结

目前Spark Streaming 可以应对的场景不少,但是在很多场景上,还是有这样那样的问题。建议调研后都进一步做测试再做出是否迁移到该平台的决定。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值