仅在滑动窗口上连接流事件一次

时间:2018-03-09 22:16:49

标签: apache-flink

我试图评估apache flink是否可用于分布式事件驱动系统(仅一次)。用例是用户注册订阅并希望更改其他订阅。

当用户单击提交按钮时,有两个单独的进程异步运行。一个进程取消现有订阅,而另一个进程注册新订阅。触发这两个事件后,将发送电子邮件通知。

我设法使用RabbitMQ连接器在apache flink中创建了两个流。当我尝试使用滑动窗口将这些流连接在一起时,窗口中的每个幻灯片都会复制事件。我已尝试在已加入的流上设置ValueStateDescriptor,但在窗口过后,这似乎没有过期。

此外,我需要检测尚未在流中配对的事件,并将此事件发送到另一个RabbitMQ接收器,以应对由于流程未成功完成而未触发事件的情况。

您对如何实现上述功能有任何提示/想法吗?

    final StreamExecutionEnvironment environment = StreamExecutionEnvironment.getExecutionEnvironment();
    environment.setStreamTimeCharacteristic(TimeCharacteristic.IngestionTime);

    final RMQConnectionConfig rmqConnectionConfig = new RMQConnectionConfig.Builder()
            .setHost("localhost")
            .setPort(5672)
            .setVirtualHost("/")
            .setUserName("admin")
            .setPassword("password")
            .build();

    final DataStream<String> cancellation = environment
            .addSource(new RMQSource<>(rmqConnectionConfig, "scratchpad-cancellation", true, new SimpleStringSchema()))
            .setParallelism(1);

    final DataStream<String> subscription = environment
            .addSource(new RMQSource<>(rmqConnectionConfig, "scratchpad-subscription", true, new SimpleStringSchema()))
            .setParallelism(1);

    cancellation
            .join(subscription)
            .where(value -> value).equalTo(value -> value)
            .window(SlidingEventTimeWindows.of(Time.minutes(5), Time.seconds(15)))
            .apply((left, right) -> left)
            .keyBy(value -> value)
            .process(new ProcessFunction<String, String>() {

                private ValueStateDescriptor<Boolean> descriptor = new ValueStateDescriptor<>("seen", Boolean.class);
                private ValueState<Boolean> state;

                @Override
                public void open(Configuration parameters) {
                    state = this.getRuntimeContext().getState(descriptor);
                }

                @Override
                public void processElement(String value, Context ctx, Collector<String> out) throws Exception {
                    if (BooleanUtils.isNotTrue(state.value())) {
                        state.update(true);
                        out.collect(value);

                        ctx.timerService().registerEventTimeTimer(ctx.timestamp() + TimeUnit.MILLISECONDS.convert(10, TimeUnit.MINUTES));
                    }
                }

                @Override
                public void onTimer(long timestamp, OnTimerContext ctx, Collector<String> out) {
                    state.clear();
                }
            })
            .print()
            .setParallelism(1);

    environment.execute();

1 个答案:

答案 0 :(得分:0)

如果窗口输出上有重复值,则可以在已定义的幻灯片窗口之后将reduce函数添加到另一个窗口中,并且在大多数情况下应该很简单。但我认为这应该是一个比这更好的解决方案,但我们需要一个代码的例子来进行改进。

另一方面,如果您需要检测非配对事件,我认为您需要使用CoGroup operator,而不是使用连接。