我们有2个流,我们称它们为A
和B
。
它们分别产生元素a
和b
。
流A
产生元素的速度很慢(每分钟一个)。
流B
每2周接收一次单个元素。它使用flatMap
函数,该函数接收此元素并在循环中生成约200万个b
元素:
(Java)
for (BElement value : valuesList) {
out.collect(updatedTileMapVersion);
}
此处的valueList
包含约200万个b
元素
我们使用A
连接这些流(B
和connect
),通过某个键进行键操作,并在连接的流上执行另一个flatMap
:
streamA.connect(streamB).keyBy(AClass::someKey, BClass::someKey).flatMap(processConnectedStreams)
每个b
元素都有一个不同的密钥,这意味着有约200万个密钥来自B
流。
我们看到的是饥饿。即使有a
个元素已准备好进行处理,它们也不会在processConnectedStreams
中进行处理。
我们尝试通过每10个元素执行一次B
,在1秒内将流Thread.sleep()
限制为10个元素:
long totalSent = 0;
for (BElement value : valuesList) {
totalSent++;
out.collect(updatedTileMapVersion);
if (totalSent % 10 == 0) {
Thread.sleep(1000)
}
}
模拟processConnectedStreams
与另一个Thread.sleep()
花费1秒钟,我们尝试使用:
*对所有管道设置10的并行度-不起作用
*为所有管道设置15的并行度-确实有效
我们不希望使用所有这些资源,因为流B
很少被激活,而对于流A
来说,具有高度并行性的元素就显得过分了。
是否可以在不将并行度设置为超过我们每秒发送的b
个元素的数量的情况下解决它?
答案 0 :(得分:0)
如果您共享完整的工作流拓扑,这将很有用。例如,您没有提及对数据进行任何键控或随机分区。如果真是这样,那么Flink将在一项任务中管线化多个操作,这可能(取决于拓扑结构)导致您遇到的问题。
如果是这种情况,那么在processConnectedStreams
之前强制分区会有所帮助,因为该操作将从网络缓冲区读取。