Java 结合BigQuery和发布/订阅Apache Beam

Java 结合BigQuery和发布/订阅Apache Beam,java,google-cloud-dataflow,apache-beam,Java,Google Cloud Dataflow,Apache Beam,我正在尝试使用DataFlowRunner执行以下操作: 从分区的BigQuery表读取数据(大量数据,但仅获取最后两天的数据) 从发布/订阅中读取JSON 在公共密钥上联接两个集合 将联接的集合插入另一个BigQuery表 我对ApacheBeam非常陌生,所以我不能100%确定我想做的是可能的 我的问题是,当我尝试连接两行时,在使用CoGroupByKey转换后,尽管窗口策略是相同的(30秒固定窗口、窗口结束触发器和丢弃触发窗格),但数据似乎从未在同一时间到达 我的一些相关代码块:

我正在尝试使用DataFlowRunner执行以下操作:

  • 从分区的BigQuery表读取数据(大量数据,但仅获取最后两天的数据)
  • 从发布/订阅中读取JSON
  • 在公共密钥上联接两个集合
  • 将联接的集合插入另一个BigQuery表
  • 我对ApacheBeam非常陌生,所以我不能100%确定我想做的是可能的

    我的问题是,当我尝试连接两行时,在使用CoGroupByKey转换后,尽管窗口策略是相同的(30秒固定窗口、窗口结束触发器和丢弃触发窗格),但数据似乎从未在同一时间到达

    我的一些相关代码块:

        /* Getting the data and windowing */
        PCollection<PubsubMessage> pubsub = p.apply("ReadPubSub sub",PubsubIO.readMessages().fromSubscription(SUB_ALIM_REC));
    
        String query = /* The query */
        PCollection<TableRow> bqData = p.apply("Reading BQ",BigQueryIO.readTableRows().fromQuery(query).usingStandardSql())
                .apply(Window.<TableRow>into(FixedWindows.of(Duration.standardSeconds(30)))
                        .triggering(AfterWatermark.pastEndOfWindow())
                        .withAllowedLateness(Duration.standardSeconds(0)).accumulatingFiredPanes());        
    
        PCollection<TableRow> tableRow = pubsub.apply(Window.<PubsubMessage>into(FixedWindows.of(Duration.standardSeconds(120)))
                .triggering(AfterWatermark.pastEndOfWindow())
                .withAllowedLateness(Duration.standardSeconds(0)).accumulatingFiredPanes())
                .apply("JSON to TableRow",ParDo.of(new ToTableRow()));
    
    
    
        /*  Join code   */  
        PCollection<TableRow> finalResultCollection =
                    kvpCollection.apply("Join TableRows", ParDo.of(
                            new DoFn<KV<Long, CoGbkResult>,  TableRow>() {
                                private static final long serialVersionUID = 6627878974147676533L;
    
                        @ProcessElement
                        public void processElement(ProcessContext c) {
                            KV<Long, CoGbkResult> e = c.element();
                            Long idPaquete = e.getKey();
                            Iterable<TableRow> it1 = e.getValue().getAll(packTag);
                            Iterable<TableRow> it2 = e.getValue().getAll(alimTag);
                            for(TableRow t1 : itPaq) {
                                for (TableRow t2 : itAlimRec) {
                                    TableRow joinedRow = new TableRow();
                                    /* set the required fields from each collection */
                                    c.output(joinedRow);
                                }
    
                            }
                        }
                    }));
    

    我非常感谢您的指导,让我知道我正在尝试的方法是否可行,或者是否有其他方法可以解决此问题。

    我也尝试过同样的方法。据我所知,目前这是不可能的。我试着自己做这件事,使用周期脉冲,跟随(尽管我不想要旁侧输入)。我编写了类似以下代码的,得到了
    ValueError:BigQuery源代码当前不可用于流式管道。

    segments = p | 'triggering segments fetch' >> PeriodicImpulse() \
           | "loading segments" >> beam.io.Read(beam.io.BigQuerySource(
                use_standard_sql=True,
            query=f'''
                SELECT 
                    id,
                    segment
                FROM `some_table`''')) \
           | "windowing info" >> beam.WindowInto(window.FixedWindows(5))
    
    info = p | "reading info" >> beam.io.ReadFromPubSub(
        topic='my_test_topic') \
           | "parsing info" >> beam.Map(message_to_json) \
           | "mapping info" >> beam.Map(lambda x: (x['id'], x['username'])) \
           | "windowing info" >> beam.WindowInto(window.FixedWindows(5))
    
    results = ({'segments': segments, 'info': info} | beam.CoGroupByKey()) | "printing" >> beam.Map(print_out)
    

    我认为目前最好的解决方案是使用数据存储之类的外部存储。我在另一条生产线中使用了这种方法,效果非常好。您可以找到解释。

    我不确定您的BigQuery结果是否需要一个定时窗口,是吗?也许你应该看看侧面输入
    segments = p | 'triggering segments fetch' >> PeriodicImpulse() \
           | "loading segments" >> beam.io.Read(beam.io.BigQuerySource(
                use_standard_sql=True,
            query=f'''
                SELECT 
                    id,
                    segment
                FROM `some_table`''')) \
           | "windowing info" >> beam.WindowInto(window.FixedWindows(5))
    
    info = p | "reading info" >> beam.io.ReadFromPubSub(
        topic='my_test_topic') \
           | "parsing info" >> beam.Map(message_to_json) \
           | "mapping info" >> beam.Map(lambda x: (x['id'], x['username'])) \
           | "windowing info" >> beam.WindowInto(window.FixedWindows(5))
    
    results = ({'segments': segments, 'info': info} | beam.CoGroupByKey()) | "printing" >> beam.Map(print_out)