Google cloud dataflow 在Apache Beam中创建自定义窗口函数

Google cloud dataflow 在Apache Beam中创建自定义窗口函数,google-cloud-dataflow,apache-beam,dataflow,Google Cloud Dataflow,Apache Beam,Dataflow,我有一个Beam管道,它从读取多个文本文件开始,其中文件中的每一行表示一行,该行稍后将插入管道中的Bigtable中。该场景需要确认从每个文件中提取的行数以及随后插入到Bigtable中的行数是否匹配。为此,我计划开发一种自定义窗口策略,以便根据文件名将单个文件中的行分配给单个窗口,该文件名是传递给窗口功能的键 是否有用于创建自定义窗口功能的代码示例?尽管我更改了确认插入行数的策略,但对于对批处理作业中从批处理源读取的窗口元素(例如FileIO)感兴趣的人,以下是创建自定义窗口策略的代码: pu

我有一个Beam管道,它从读取多个文本文件开始,其中文件中的每一行表示一行,该行稍后将插入管道中的Bigtable中。该场景需要确认从每个文件中提取的行数以及随后插入到Bigtable中的行数是否匹配。为此,我计划开发一种自定义窗口策略,以便根据文件名将单个文件中的行分配给单个窗口,该文件名是传递给窗口功能的键


是否有用于创建自定义窗口功能的代码示例?

尽管我更改了确认插入行数的策略,但对于对批处理作业中从批处理源读取的窗口元素(例如
FileIO
)感兴趣的人,以下是创建自定义窗口策略的代码:

public class FileWindows extends PartitioningWindowFn<Object, IntervalWindow>{

private static final long serialVersionUID = -476922142925927415L;
private static final Logger LOG = LoggerFactory.getLogger(FileWindows.class);

@Override
public IntervalWindow assignWindow(Instant timestamp) {
    Instant end = new Instant(timestamp.getMillis() + 1);
    IntervalWindow interval = new IntervalWindow(timestamp, end);
    LOG.info("FileWindows >> assignWindow(): Window assigned with Start: {}, End: {}", timestamp, end);
    return interval;
}

@Override
public boolean isCompatible(WindowFn<?, ?> other) {
    return this.equals(other);
}

@Override
public void verifyCompatibility(WindowFn<?, ?> other) throws IncompatibleWindowException {
    if (!this.isCompatible(other)) {
        throw new IncompatibleWindowException(other, String.format("Only %s objects are compatible.", FileWindows.class.getSimpleName()));
    }
  }

@Override
public Coder<IntervalWindow> windowCoder() {
    return IntervalWindow.getCoder();
}   
公共类文件窗口扩展了分区窗口fn{
私有静态最终长serialVersionUID=-476922142925927415L;
私有静态最终记录器LOG=LoggerFactory.getLogger(FileWindows.class);
@凌驾
公共间隔窗口(即时时间戳){
瞬间结束=新的瞬间(timestamp.getMillis()+1);
IntervalWindow interval=新的IntervalWindow(时间戳,结束);
LOG.info(“FileWindows>>assignWindow():窗口分配了开始:{},结束:{}”,时间戳,结束);
返回间隔;
}
@凌驾
公共布尔值不可计算(WindowFn其他){
返回此。等于(其他);
}
@凌驾
public void verifyCompatibility(WindowFn其他)引发不兼容的indowException{
如果(!this.isCompatible(其他)){
抛出新的不兼容IndowException(其他,String.format(“只有%s对象是兼容的。”,FileWindows.class.getSimpleName());
}
}
@凌驾
公共编码器windowCoder(){
返回IntervalWindow.getCoder();
}   
}

然后可以在管道中使用,如下所示:

p
 .apply("Assign_Timestamp_to_Each_Message", ParDo.of(new AssignTimestampFn()))
 .apply("Assign_Window_to_Each_Message", Window.<KV<String,String>>into(new FileWindows())
  .withAllowedLateness(Duration.standardMinutes(1))
  .discardingFiredPanes());
p
.apply(“为每条消息分配时间戳”),ParDo.of(new assigntimestamp())
.apply(“为每条消息分配\u窗口”,Window.into(新文件窗口())
.允许迟到(持续时间.标准分钟(1))
.丢弃火锅());

请记住,您需要编写
AssignTimestampFn()
,以便每条消息都带有时间戳。

这是流式管道吗?如果没有,您可以使用GroupByKey@Pablo谢谢你的回复。然而,基于我有限的知识和查看文档,
GroupByKey
仅充当SQL
groupby
&实际上并不分配窗口。在我的场景中,这些行已经根据作为容器(即密钥)的文件名分组在一起。这里的问题是能够将属于同一文件的行(行)作为同一窗口的一部分插入,我认为如果在调用
CloudBigtableIO.WriteTable()
之前将这些行设置为同一窗口的一部分,这是可能的。我不明白您的意思。如果已按文件名将行分组,为什么需要插入其他行?这些其他的线路是从哪里来的?很抱歉搞混了。当我说“行已经根据文件名分组在一起了”时,基本上我想说的是我已经知道特定行属于哪个文件。这不是问题所在。问题是调用
CloudBigtableIO.WriteTable()
,这需要按每个窗口(1个文件名=1个窗口)进行。不幸的是,
GroupByKey
不会为每个键创建窗口。希望他的解释清楚。光束窗口中的Hmmm用于表示时间,而不是其他维度。如果要对元素进行窗口化,则必须添加时间戳,并应用窗口化策略。您可以添加自定义的时间窗口策略,但这似乎不是您想要的?