Google cloud dataflow 使用默认触发器在windows中使用无界数据

Google cloud dataflow 使用默认触发器在windows中使用无界数据,google-cloud-dataflow,apache-beam,Google Cloud Dataflow,Apache Beam,我有一个topic+订阅,并希望在一个应用程序中使用和聚合订阅中的无限数据。我使用一个固定的窗口并将聚合写入BigQuery Window.Bound<String> w = Window.<String>into(FixedWindows.of(Duration.standardSeconds(1))) .triggering(AfterProcessingTime .pastFirstElementInPane()

我有一个topic+订阅,并希望在一个应用程序中使用和聚合订阅中的无限数据。我使用一个固定的窗口并将聚合写入BigQuery

Window.Bound<String> w = Window.<String>into(FixedWindows.of(Duration.standardSeconds(1)))
        .triggering(AfterProcessingTime
                .pastFirstElementInPane()
                .plusDelayOf(Duration.standardSeconds(1)))
        .withAllowedLateness(Duration.ZERO)
        .discardingFiredPanes();
读和写(没有窗口和聚合)工作正常。但是,当我将数据管道化到一个固定的窗口(计算每个窗口中的元素)中时,该窗口永远不会关闭。因此,没有编写聚合

这是我的word publisher(它使用来自的kinglear.txt作为输入文件):

public静态类AddCurrentTimestampFn扩展了DoFn{
@ProcessElement公共无效ProcessElement(ProcessContext c){
c、 outputWithTimestamp(c.element(),新的Instant(System.currentTimeMillis());
}
}
公共静态类ExtractWordsFn扩展了DoFn{
@ProcessElement公共无效ProcessElement(ProcessContext c){
字符串[]words=c.element().split([^a-zA-Z']+”;
对于(字符串字:字){if(!word.isEmpty()){c.output(字);}
}
}
//主要内容:
管道p=管道。创建(o);/'o’管道选项是什么
p、 apply(“ReadLines”,TextIO.Read.from(o.getInputFile()))
.apply(“Lines2Words”,ParDo.of(new ExtractWordsFn()))
.apply(“AddTimestampFn”,ParDo.of(new AddCurrentTimestampFn()))
.apply(“WriteTopic”,publisubio.Write.topic(o.getTopic());
p、 run();
这是我的窗口字计数器:

Pipeline p = Pipeline.create(o); // 'o' are the pipeline options

BigQueryIO.Write.Bound tablePipe = BigQueryIO.Write.to(o.getTable(o))
        .withSchema(o.getSchema())
        .withCreateDisposition(BigQueryIO.Write.CreateDisposition.CREATE_IF_NEEDED)
        .withWriteDisposition(BigQueryIO.Write.WriteDisposition.WRITE_APPEND);

Window.Bound<String> w = Window
        .<String>into(FixedWindows.of(Duration.standardSeconds(1)));

p.apply("ReadTopic", PubsubIO.Read.subscription(o.getSubscription()))
        .apply("FixedWindow", w)
        .apply("CountWords", Count.<String>perElement())
        .apply("CreateRows", ParDo.of(new WordCountToRowFn()))
        .apply("WriteRows", tablePipe);
p.run();
Pipeline p=Pipeline.create(o);/'o’管道选项是什么
BigQueryIO.Write.Bound tablePipe=BigQueryIO.Write.to(o.getTable(o))
.withSchema(o.getSchema())
.withCreateDisposition(BigQueryIO.Write.CreateDisposition.CREATE如果需要)
.withWriteDisposition(BigQueryIO.Write.WriteDisposition.Write\u-APPEND);
Window.Bound w=Window
.进入(固定窗口)(持续时间标准秒(1));
p、 apply(“ReadTopic”,PubsubIO.Read.subscription(o.getSubscription()))
.应用(“固定窗口”,w)
.apply(“CountWords”,Count.perElement())
.apply(“CreateRows”,ParDo.of(new WordCountToRowFn()))
.apply(“WriteRows”,tablePipe);
p、 run();
上述订阅服务器将无法工作,因为窗口似乎不会使用触发。但是,如果我手动定义一个触发器,代码就会工作,计数就会写入BigQuery

Window.Bound<String> w = Window.<String>into(FixedWindows.of(Duration.standardSeconds(1)))
        .triggering(AfterProcessingTime
                .pastFirstElementInPane()
                .plusDelayOf(Duration.standardSeconds(1)))
        .withAllowedLateness(Duration.ZERO)
        .discardingFiredPanes();
Window.Bound w=Window.into(FixedWindows.of(Duration.standardSeconds(1)))
.触发(后处理时间
.pastFirstElementInPane()
.plusDelayOf(持续时间.standardSeconds(1)))
.允许延迟(持续时间为零)
.丢弃燃烧的汽油();
如果可能的话,我希望避免指定自定义触发器

问题:

  • 为什么我的解决方案与Dataflow的不兼容
  • 如何更改发布服务器或订阅服务器以使用触发windows

  • 你如何确定触发器从不触发

    您的
    PubSubIO.Write
    PubSubIO.Read
    转换都应该使用
    withTimestampLabel
    指定时间戳标签,否则您添加的时间戳将不会写入PubSub,并且将使用发布时间

    无论哪种方式,管道的输入水印都将从PubSub中等待的元素的时间戳中派生。一旦处理完所有输入,它将在进入实时之前停留几分钟(以防发布服务器出现延迟)

    您可能看到的是,所有元素都发布在相同的~1秒窗口中(因为输入文件非常小)。这些都是相对快速地读取和处理的,但它们放入的1秒窗口将不会触发,直到输入水印已前进,表明该1秒窗口中的所有数据已被消耗

    直到几分钟后才会发生这种情况,这可能会使触发器看起来不起作用。您编写的触发器在1秒的处理时间后触发,这将更早触发,但不能保证所有数据都已处理

    从默认触发器获得更好行为的步骤:

  • 在写入和读取子步骤上使用
    with timestamplabel
  • 让发布者将时间戳进一步分散(例如,运行几分钟并将时间戳分散在该范围内)

  • 你有作业ID吗?请注意,你的触发器将在一次触发后“完成”,删除所有进一步的数据。要匹配默认触发器,您需要使用此触发器反复测试
    永久(AfterWatermark.pastEndOfWindow())
    (如果允许的延迟为零,则不会实际重复)。但是基于水印的东西在描述的场景中不起作用。“CountWords”步骤的内部
    Combine.GroupedValues
    操作从未执行;即使在一段时间后,让管道运行>10分钟。“CountWord”的
    GroupByKey
    操作是最后执行的操作。我现在将研究/尝试Ben提出的
    时间标签
    方法@jkff:作业ID是:2017-01-04_07_33_56-14457038567248221079机械地说,一个人会如何“将时间戳分散到该范围”?从rabbitmq而不是pubsub读取时,我有一个类似的问题,但我认为我的一般问题是相同的:消息在相同的“事件时间”中出现,我有固定的1个窗口,但GBK操作永远不会完成,因为它似乎永远在等待水印前进。