我想运行一个Spark作业,每个RDD负责通过网络连接发送某些流量。每个RDD的返回值不是很重要,但我或许可以要求它们返回发送的消息数。重要的部分是网络流量,这基本上是在每个RDD上运行功能的副作用。
在Spark中执行上述任务是个好主意吗?
我正在尝试模拟来自多个来源的网络流量,以测试接收端的数据收集基础架构。我可以手动设置多台机器来运行发送器,但我认为如果我可以利用Spark现有的分布式框架会很好。
然而,似乎Spark专为程序设计“计算”然后“返回”某些东西,而不是程序运行它们的副作用。我不确定这是不是一个好主意,并希望得到别人的意见。
要清楚,我正在考虑以下内容
IDs = sc.parallelize(range(0, n))
def f(x):
for i in range(0,100):
message = make_message(x, i)
SEND_OVER_NETWORK(message)
return (x, 100)
IDsOne = IDs.map(f)
counts = IDsOne.reduceByKey(add)
for (ID, count) in counts.collect():
print ("%i ran %i times" % (ID, count))
答案 0 :(得分:2)
一般来说,它没有意义:
Spark并发具有相对较低的粒度,分区是并发的主要单位。在这个级别,处理变得同步。在完成当前分区之前,您无法转到下一个分区。
让我们说在你的情况下只有一个慢SEND_OVER_NETWORK
。如果使用map
,则几乎会阻止整个分区的处理。您可以使用mapPartitions
进入较低级别,使SEND_OVER_NETWORK
异步,并仅在处理完整个分区时返回。它更好但仍然不是最理想的。
您可以增加分区数量,但这意味着更高的簿记费用,因此在一天结束时您可能会使情况变得更糟而不是更好。
Spark API主要用于无副作用的操作。这使得难以表达不适合该模型的操作。
可以说更重要的是Spark只保证每个操作至少执行一次(如果rdd从未实现,则忽略零次)。如果应用程序需要例如一次性语义,那么事情变得棘手,尤其是当您考虑第2点时。
可以跟踪主Spark逻辑之外的每个分区的本地状态,但是如果你到达那里,那么Spark就不是正确的工具了。