Scala 拆分&;在ApacheFlink中加入流

Scala 拆分&;在ApacheFlink中加入流,scala,stream,apache-flink,Scala,Stream,Apache Flink,我想我有一个相当非标准的用例。我想使用filter功能将源流拆分为多个流: val dataStream:DataStream[MyEvent] = ... val s1 = dataStream.filter(...).map(...) val s2 = dataStream.filter(...).map(...) 我还有一个时间戳提取器(传入事件将有一个XML格式的时间戳): 我之所以选择这种方法,是因为我想构建一个可以拆分/组合任意流(例如s1+s2->c1,s1+s3->c2,c2+

我想我有一个相当非标准的用例。我想使用
filter
功能将源流拆分为多个流:

val dataStream:DataStream[MyEvent] = ...
val s1 = dataStream.filter(...).map(...)
val s2 = dataStream.filter(...).map(...)
我还有一个时间戳提取器(传入事件将有一个XML格式的时间戳):

我之所以选择这种方法,是因为我想构建一个可以拆分/组合任意流(例如s1+s2->c1,s1+s3->c2,c2+s4->c3,)的网络,而不是简单地执行单个流(
val s=dataStream.filter(…).map(…).filter(…).map(…).filter(…).map(…).map(…)

现在,当通过上述示例发送事件时,事件E1可能同时在s1和s2中结束。这意味着,在我的理解中,非常相同的事件E1作为第一个实例放入s1(E1a),并且作为第二个实例放入s2(E1b)

所以我现在想做的是把E1a和E1b重新组合成一个组合的E1,它类似于E1,作为s1和s2的变换

我试过:

val c1 = s1.join(s2)
  .where(_.key).equalTo(_.key)
  .window(TumblingEventTimeWindows.of(Time.seconds(10)))
  .apply((e1a, e2b) => { printf("Got e1a and e1b"); e1a })
然而,事件似乎从未到达应用函数,我也不知道为什么


我的例子有什么不对?我关于这样的流网络的方法/想法会奏效吗?

你有没有安排好水印?使用事件时间时,仅当水印到达并将事件时间时钟提前到窗口末尾时,才会触发窗口。您可以使用时间戳提取器/水印生成器来实现这一点;有关更多详细信息,请参阅

如果其中一个流有时处于空闲状态,这也会导致问题,因为空闲流上缺少水印将阻止它连接到的任何流的水印


根据您正试图执行的操作,您可能会发现使用协处理函数比使用时间窗口联接更容易。例如,查看Flink培训网站上的练习。

查看
联合
,而不是
加入
。您能详细介绍一下吗?如何使用
union
函数实现相同的功能?无需担心;我没有仔细阅读你的问题。我编辑了我的帖子来描述时间戳函数。在我的测试中,我只使用了一个事件,它将进入
dataStream
,然后进入
s1
s2
。因此,
s1
s2
中只有两个事件实例具有相同的时间戳。我将尝试有状态的扩展变体,看看它是如何运行的。然而,有一个问题。在尝试构建流网络时,我可能会遇到多个连接(通过connect/CoProcessFunction实现),它们处理相同的事件。这可能不适用于存储状态,因为键/事件对于多个联接是相同的?如果只有一个事件,那么这就解释了为什么窗口从不触发。对于事件时间窗口,必须在窗口后有一个带有时间戳的水印,才能触发窗口。生成这样的水印需要第二个事件。此外,时间戳提取器假定事件按时间戳顺序排列。如果这是真的,您应该只使用AscendingTimestampExtractor。多个联接(每个键)可以工作,但每个联接都必须管理自己的状态——联接之间无法共享状态。好的,这很好。事实上,我测试了这项技术,它非常有效。当E1进入管道时,它被分配了一个UUID,稍后我将使用该UUID对所有流进行键控,并在
RichCoFlatMapFunction
中再次匹配事件实例。由于我计划建立一个潜在的大型流网络,使用
过滤器
-和
连接
-功能进行分叉/连接,您认为当流的数量变大时,这种方法会成为一个问题吗?我正在寻找最佳的/正确的方法来最大程度地利用FLink在集群环境中的能力。你应该考虑使用叉输出来进行分叉——这可能会产生比过滤器更干净、性能更高的解决方案(参见)。但除此之外,这应该很好——这种总体方法相当普遍。
val c1 = s1.join(s2)
  .where(_.key).equalTo(_.key)
  .window(TumblingEventTimeWindows.of(Time.seconds(10)))
  .apply((e1a, e2b) => { printf("Got e1a and e1b"); e1a })