Apache flink APACHE FLINK AggregateFunction与tumblingWindow一起计算事件,但如果没有发生任何事件,也会发送0
我需要在翻滚的窗口中计算事件。但如果窗口中没有事件,我还希望发送值为0的事件 差不多Apache flink APACHE FLINK AggregateFunction与tumblingWindow一起计算事件,但如果没有发生任何事件,也会发送0,apache-flink,flink-streaming,Apache Flink,Flink Streaming,我需要在翻滚的窗口中计算事件。但如果窗口中没有事件,我还希望发送值为0的事件 差不多 窗口数:5 窗口计数:0 窗口计数:0 窗口数:3 窗口计数:0 import com.google.protobuf.Message; 导入org.apache.flink.api.common.functions.AggregateFunction; 导入org.skydivin4ng3l.cepmodemon.models.events.aggregate.aggregateOutterClass; 公
import com.google.protobuf.Message;
导入org.apache.flink.api.common.functions.AggregateFunction;
导入org.skydivin4ng3l.cepmodemon.models.events.aggregate.aggregateOutterClass;
公共类BasicCounter实现AggregateFunction{
@凌驾
公共长事务累加器(){
返回0升;
}
@凌驾
公共长添加(T事件,长累加器){
回油蓄能器+1L;
}
@凌驾
公共AggregateOutterClass.Aggregate getResult(长累加器){
返回AggregateOutterClass.Aggregate.newBuilder().setVolume(累加器).build();
}
@凌驾
公共长合并(长累加器1、长累加器2){
回流蓄能器1+蓄能器2;
}
}
在这里使用
DataStream<AggregateOuterClass.Aggregate> aggregatedStream = someEntryStream
.windowAll(TumblingEventTimeWindows.of(Time.seconds(5)))
.aggregate(new BasicCounter<MonitorOuterClass.Monitor>());
datastreamaggregatedstream=someEntryStream
.windowAll(TumblingEventTimeWindows.of(时间秒(5)))
.合计(新基本会计科目());
时间特征是摄入时间
我读过一篇关于Tigger函数的文章,该函数可以检测聚合流是否在x时间之后接收到事件,但我不确定这样做是否正确
即使窗口中根本没有事件,我也希望聚合会发生。也许有一个我不知道的环境
谢谢你的任何提示 Flink的窗口是在第一个事件分配给窗口时延迟创建的。因此,空窗口不存在,并且不能产生结果 通常有三种方法可以解决此问题:
ProcessFunction
实现自己的窗口。但在这里,您仍将面临需要使用处理时间计时器的问题触发器
,如果窗口为空,也不会调用ProcessAllWindowFunction
,因此必须始终在全局窗口
中至少保留一个元素。这似乎需要实现一个相当粗糙的逐出器
和ProcessAllWindowFunction
,它们协作来保留和忽略窗口中的一个特殊元素——而且您还必须首先以某种方式将该元素放入窗口中
如果你打算做一些骇客的事情,那么选项1似乎要简单得多。我按照@David Anderson的建议选择了选项1: 这是我的事件生成器:
public class EmptyEventSource implements SourceFunction<MonitorOuterClass.Monitor> {
private volatile boolean isRunning = true;
private final long delayPerRecordMillis;
public EmptyEventSource(long delayPerRecordMillis){
this.delayPerRecordMillis = delayPerRecordMillis;
}
@Override
public void run(SourceContext<MonitorOuterClass.Monitor> sourceContext) throws Exception {
while (isRunning) {
sourceContext.collect(MonitorOuterClass.Monitor.newBuilder().build());
if (delayPerRecordMillis > 0) {
Thread.sleep(delayPerRecordMillis);
}
}
}
@Override
public void cancel() {
isRunning = false;
}
}
公共类EmptyEventSource实现SourceFunction{
private volatile boolean isRunning=true;
私人最终长延迟PerrecordMillis;
公共EmptyEventSource(长延迟PerRecordMillis){
this.delayPerRecordMillis=delayPerRecordMillis;
}
@凌驾
公共void运行(SourceContext SourceContext)引发异常{
同时(正在运行){
collect(MonitorOuterClass.Monitor.newBuilder().build());
如果(delayPerRecordMillis>0){
睡眠(delayPerRecordMillis);
}
}
}
@凌驾
公开作废取消(){
isRunning=false;
}
}
以及我的调整聚合功能:
public class BasicCounter<T extends Message> implements AggregateFunction<T, Long, AggregateOuterClass.Aggregate> {
@Override
public Long createAccumulator() {
return 0L;
}
@Override
public Long add(T event, Long accumulator) {
if(((MonitorOuterClass.Monitor)event).equals(MonitorOuterClass.Monitor.newBuilder().build())) {
return accumulator;
}
return accumulator + 1L;
}
@Override
public AggregateOuterClass.Aggregate getResult(Long accumulator) {
AggregateOuterClass.Aggregate newAggregate = AggregateOuterClass.Aggregate.newBuilder().setVolume(accumulator).build();
return newAggregate;
}
@Override
public Long merge(Long accumulator1, Long accumulator2) {
return accumulator1 + accumulator2;
}
}
public类BasicCounter实现AggregateFunction{
@凌驾
公共长事务累加器(){
返回0升;
}
@凌驾
公共长添加(T事件,长累加器){
if(((MonitorOuterClass.Monitor)事件)。等于(MonitorOuterClass.Monitor.newBuilder().build()){
回流蓄能器;
}
回油蓄能器+1L;
}
@凌驾
公共AggregateOutterClass.Aggregate getResult(长累加器){
AggregateOuterClass.Aggregate newAggregate=AggregateOuterClass.Aggregate.newBuilder().setVolume(累加器).build();
返回新集合;
}
@凌驾
公共长合并(长累加器1、长累加器2){
回流蓄能器1+蓄能器2;
}
}
他们是这样使用的:
DataStream<MonitorOuterClass.Monitor> someEntryStream = env.addSource(currentConsumer);
DataStream<MonitorOuterClass.Monitor> triggerStream = env.addSource(new EmptyEventSource(delayPerRecordMillis));
DataStream<AggregateOuterClass.Aggregate> aggregatedStream = someEntryStream
.union(triggerStream)
.windowAll(TumblingProcessingTimeWindows.of(Time.seconds(5)))
.aggregate(new BasicCounter<MonitorOuterClass.Monitor>());
DataStream someEntryStream=env.addSource(currentConsumer);
DataStream triggerStream=env.addSource(新的EmptyEventSource(delayPerRecordMillis));
DataStream aggregatedStream=someEntryStream
.union(triggerStream)
.windowAll(TumblingProcessingTimeWindows.of(时间秒(5)))
.合计(新基本会计科目());
选择选项2。我不明白如何正确设置触发器DataStream aggregatedStream=someEntryStream.windowAll(GlobalWindows.create()/*TumblingEventTimeWindows.of(Time.seconds(5))*/).trigger(new PurgingTrigger(ProcessingTimeTrigger.create()).aggregate(new BasicCounter())代码>我有点困惑如何使用这个,你能提供一个例子吗?我花了大量时间试图写一个我可以分享的好例子,但我放弃了。请看我的更新答案。我现在正在做选项1=),因为我也放弃了选项2。它可能正在工作,但现在我有一个Protobuf问题,0不能是一个值,而对象是空的。但至少它起作用了=)
DataStream<MonitorOuterClass.Monitor> someEntryStream = env.addSource(currentConsumer);
DataStream<MonitorOuterClass.Monitor> triggerStream = env.addSource(new EmptyEventSource(delayPerRecordMillis));
DataStream<AggregateOuterClass.Aggregate> aggregatedStream = someEntryStream
.union(triggerStream)
.windowAll(TumblingProcessingTimeWindows.of(Time.seconds(5)))
.aggregate(new BasicCounter<MonitorOuterClass.Monitor>());