Java 结合BigQuery和发布/订阅Apache Beam
我正在尝试使用DataFlowRunner执行以下操作:Java 结合BigQuery和发布/订阅Apache Beam,java,google-cloud-dataflow,apache-beam,Java,Google Cloud Dataflow,Apache Beam,我正在尝试使用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)