我试图在我的4核计算机的本地模式下运行一些关于Spark Streaming Application处理时间的测试。
这是我的代码:
SparkConf sparkConf = new SparkConf().setMaster("local[2]").setAppName("sparkstreaminggetjson");
JavaStreamingContext ssc = new JavaStreamingContext(sparkConf, Durations.seconds(1));
JavaReceiverInputDStream<String> streamData1 = ssc.socketTextStream(args[0], Integer.parseInt(args[1]),
StorageLevels.MEMORY_AND_DISK_SER);
streamData1.print();
我每秒收到1条JSON消息。 所以,我测试了4个不同的场景:
1)setMaster(...local[2])
和1分区
2)setMaster(...local[*])
和1分区
3)setMaster(...local[2])
和4个分区(使用streamData1.repartition(4)
)
4)setMaster(...local[*])
和4个分区(使用streamData1.repartition(4)
)
当我检查用户界面中的平均处理时间时,这是我为每种方案获得的:
1)30毫秒
2)28 ms
3)72 ms
4)75毫秒
我的问题是:为什么1和2,3和4的处理时间几乎相同? 我意识到例如从2增加到4是正常的,因为重新分区是一种随机操作。我没有得到的是,例如4),为什么处理与3类似?因为我提高了并列化的水平,所以它不应该小得多,我有更多的核心来分配任务吗?
希望我不会感到困惑, 非常感谢你。
答案 0 :(得分:1)
其中一些取决于您的JSON消息的样子,我假设每条消息都是一个没有换行符的字符串。在这种情况下,每秒有1条消息,批处理间隔为1秒,在每个批次中,您将获得仅包含一个项目的RDD。您无法将其拆分为多个分区,因此在重新分区时,您仍然可以在数据方面获得相同的情况,但需要重新分配步骤的开销。
即使数据量较大,当您对数据所做的只是print()
时,我也不会期望太大的差异:这将占用您数据的前10项,如果它们可以来自一个分区,我希望Spark优化它只计算一个分区。在任何情况下,如果您显着增加每批数据量,并在整个集合上进行一些实际处理,您将获得更具代表性的数字,至少类似于streamData1.count().print()
。
为了更好地理解发生的事情,深入了解Spark的其他部分也很有用,比如Stages选项卡可以告诉你执行时间有多少是洗牌,序列化等等而不是实际执行,以及影响性能的事情,如DAG,告诉您可以缓存哪些位,以及Spark能够跳过的任务。