目录
设置合理的batch interval
如果想让一个运行在集群上的Spark Streaming应用程序可以稳定,它就必须尽可能快地处理接收到的数据。确定正确的batch大小较好的方法是在一个很保守的batch interval,比如5~10s,以很慢的数据接收速率进行测试。要检查应用是否跟得上这个数据速率,可以检查每个batch的处理时间的延迟,如果处理时间与batch interval基本吻合,那么应用就是稳定的。因此想有一个稳定的配置,可以尝试提升数据处理的速度或者增加batch interval。
数据接收性能调优
设置receiver数量
- 通过网络接收数据时(比如Kafka、Flume),会将数据反序列化,并存储在Spark的内存中。
- 如果数据接收成为系统的瓶颈,那么可以考虑并行化数据接收。每一个输入DStream都会在某个Worker的Executor上启动一个Receiver,该Receiver接收一个数据流。因此可以通过创建多个输入DStream,并且配置它们接收数据源不同的分区数据,达到接收多个数据流的效果。
- 比如说,一个接收两个Kafka Topic的输入DStream,可以被拆分为两个输入DStream,每个分别接收一个topic的数据。这样就会创建两个Receiver,从而并行地接收数据,进而提升吞吐量。多个DStream可以使用union算子进行聚合,从而形成一个DStream。
调节block interval
数据接收并行度调优,除了创建更多输入DStream和Receiver以外,还可以考虑调节block interval。通过参数spark.streaming.blockInterval
可以设置block interval,默认是200ms。对于大多数Receiver来说,在将接收到的数据保存到Spark的BlockManager之前,都会将数据切分为一个一个的block。而每个batch中的block数量,则决定了该batch对应的RDD的partition的数量以及针对该RDD执行transformation操作时,创建的task的数量。每个batch对应的task数量是大约估计的,即batch interval / block interval。例如说,batch interval为2s,block interval为200ms,会创建10个task。如果每个batch的task数量太少,即低于每台机器的cpu core数量,那么就说明batch的task数量是不够的,因为所有的cpu资源无法完全被利用起来。要为batch增加block的数量,那么就减小block interval。
调整inputStream.repartition参数
使用inputStream.repartition(< number of partitions>)即可。这样就可以将接收到的batch,分布到指定数量的机器上,然后再进行进一步的操作。
数据处理并行度调优
如果在计算的任何stage中使用的并行task的数量没有足够多,那么集群资源是无法被充分利用的。可以在reduceByKey等操作中,传入第二个参数,手动指定该操作的并行度。
数据序列化调优
流式计算操作生成的持久化RDD,可能会持久化到内存中。默认持久化级别是StorageLevel.MEMORY_ONLY_SER ,会减小GC开销。使用Kryo序列化类库可以减小CPU和内存的性能开销。使用Kryo时,一定要考虑注册自定义的类,并且禁用对应引用的tracking(spark.kryo.referenceTracking)
任务启动调优
如果每秒钟启动的task过于多,比如每秒钟启动50个,那么发送这些task去Worker节点上的Executor的性能开销会很大,而且此时基本就很难达到毫秒级的延迟了。使用下述操作可以减少这方面的性能开销:
1、Task序列化:使用Kryo序列化机制来序列化task,可以减小task的大小,从而减少发送这些task到各个Worker节点上的Executor的时间。
2、执行模式:在Standalone模式下运行Spark,可以达到更少的task启动时间。
设置合理的GC
对于流式应用来说,如果要获得低延迟,肯定不想要有因为JVM垃圾回收导致的长时间延迟。有很多参数可以帮助降低内存使用和GC开销:
- DStream的持久化:正如在“数据序列化调优”中提到的,输入数据和某些操作生产的中间RDD,默认持久化时都会序列化为字节。与非序列化的方式相比,这会降低内存和GC开销。使用Kryo序列化机制可以进一步减少内存使用和GC开销。进一步降低内存使用率,可以对数据进行压缩,由spark.rdd.compress参数控制(默认false)
- 清理旧数据:默认情况下,所有输入数据和通过DStream transformation操作生成的持久化RDD,会自动被清理。
- CMS垃圾回收器:使用并行的mark-sweep垃圾回收机制,用来保持GC低开销。虽然并行的GC会降低吞吐量,但是使用它可以减少batch的处理时间(降低处理过程中的gc开销)。可以如下配置:
spark.executor.extraJavaOptions=-XX:+UseConcMarkSweepGC
设置合理的CPU资源数
很多情况下Streaming程序需要的内存不是很多,但是需要的CPU要很多。在Streaming程序中,CPU资源的使用可以分为两大类:用于接收数据和用于处理数据。需要设置足够的CPU资源,使得有足够的CPU资源用于接收和处理数据,这样才能及时高效地处理数据。