Java 数据流大端输入中的Apache Beam
这是最相似的 我正在Dataflow2.x中创建一个管道,它从Pubsub队列获取流式输入。传入的每一条消息都需要通过一个非常大的数据集进行流式传输,该数据集来自Google BigQuery,并在写入数据库之前附加所有相关值(基于一个键) 问题在于BigQuery中的映射数据集非常大—任何将其用作辅助输入的尝试都会失败,数据流运行程序会抛出错误“java.lang.IllegalArgumentException:ByteString太长”。我尝试了以下策略: 1) 侧面输入Java 数据流大端输入中的Apache Beam,java,google-bigquery,google-cloud-dataflow,apache-beam,Java,Google Bigquery,Google Cloud Dataflow,Apache Beam,这是最相似的 我正在Dataflow2.x中创建一个管道,它从Pubsub队列获取流式输入。传入的每一条消息都需要通过一个非常大的数据集进行流式传输,该数据集来自Google BigQuery,并在写入数据库之前附加所有相关值(基于一个键) 问题在于BigQuery中的映射数据集非常大—任何将其用作辅助输入的尝试都会失败,数据流运行程序会抛出错误“java.lang.IllegalArgumentException:ByteString太长”。我尝试了以下策略: 1) 侧面输入 如上所述,映射
- 如上所述,映射数据(显然)太大,无法进行此操作。如果我在这里错了,或者有解决办法,请让我知道,因为这将是最简单的解决方案
- 在这个策略中,我读取管道第一部分中的BigQuery数据和Pubsub消息数据,然后运行每个ParDo转换,将pcollection中的每个值更改为KeyValue对。然后,我运行Merge.flatte转换和GroupByKey转换,将相关映射数据附加到每条消息
- 这里的问题是,流数据需要窗口化与其他数据合并,因此我也必须将窗口化应用于大型、有界的BigQuery数据。它还要求两个数据集上的窗口策略相同。但是对于有界数据没有窗口策略是有意义的,我所做的几次窗口尝试只是在一个窗口中发送所有BQ数据,然后再也不发送它。它需要与每个传入的pubsub消息连接
- 这似乎是个好主意——让每个工作人员声明地图数据的静态实例。如果它不在那里,那么直接调用BigQuery来获取它。不幸的是,每次BigQuery都会抛出内部错误(正如整个消息中所说的“内部错误”)。向谷歌提交了一份支持票,结果他们告诉我,基本上,“你不能那样做”
java.lang.IllegalArgumentException:ByteString太长
下面是我正在使用的代码示例(psuedo):
Pipeline pipeline = Pipeline.create(options);
PCollectionView<Map<String, TableRow>> mapData = pipeline
.apply("ReadMapData", BigQueryIO.read().fromQuery("SELECT whatever FROM ...").usingStandardSql())
.apply("BQToKeyValPairs", ParDo.of(new BQToKeyValueDoFn()))
.apply(View.asMap());
PCollection<PubsubMessage> messages = pipeline.apply(PubsubIO.readMessages()
.fromSubscription(String.format("projects/%1$s/subscriptions/%2$s", projectId, pubsubSubscription)));
messages.apply(ParDo.of(new DoFn<PubsubMessage, TableRow>() {
@ProcessElement
public void processElement(ProcessContext c) {
JSONObject data = new JSONObject(new String(c.element().getPayload()));
String key = getKeyFromData(data);
TableRow sideInputData = c.sideInput(mapData).get(key);
if (sideInputData != null) {
LOG.info("holyWowItWOrked");
c.output(new TableRow());
} else {
LOG.info("noSideInputDataHere");
}
}
}).withSideInputs(mapData));
查看本文中名为“模式:流模式大型查找表”的部分(这可能是唯一可行的解决方案,因为您的端输入不适合内存): 说明: 大型(以GB为单位)查找表必须准确,并且经常或经常更改 不适合记忆 示例: 您从零售商处获得了销售点信息,需要 将产品项的名称与 包含productID。有成千上万的物品 存储在可不断更改的外部数据库中。还有,所有 必须使用正确的值处理元素 解决方案: 使用“”模式 但与其调用微服务,不如调用读优化的NoSQL 直接访问数据库(如云数据存储或云Bigtable) 对于要查找的每个值,使用KV创建一个键值对 实用类。执行GroupByKey以创建相同密钥类型的批 对数据库进行调用。在DoFn中,向 该键的数据库,然后按将该值应用于所有值 穿过这片森林。与客户一起遵循最佳实践 如“调用外部服务获取数据”中所述的实例化 浓缩” 本文介绍了其他相关模式:
- 模式:缓慢更改查找缓存
- 模式:调用外部服务以丰富数据
View.asSingleton
,View.asMap
等。?例如--View.asSingleton
将使用单个元素获取PCollection,并使其对ParDo可见<代码>视图。asMap将采用PCollection
并将其作为Map
提供,但将仅读取您需要的键。有相关消息吗?面对同样的问题
java.lang.IllegalArgumentException: ByteString would be too long: 644959474+1551393497
com.google.cloud.dataflow.worker.repackaged.com.google.protobuf.ByteString.concat(ByteString.java:524)
com.google.cloud.dataflow.worker.repackaged.com.google.protobuf.ByteString.balancedConcat(ByteString.java:576)
com.google.cloud.dataflow.worker.repackaged.com.google.protobuf.ByteString.balancedConcat(ByteString.java:575)
com.google.cloud.dataflow.worker.repackaged.com.google.protobuf.ByteString.balancedConcat(ByteString.java:575)
com.google.cloud.dataflow.worker.repackaged.com.google.protobuf.ByteString.balancedConcat(ByteString.java:575)
com.google.cloud.dataflow.worker.repackaged.com.google.protobuf.ByteString.copyFrom(ByteString.java:559)
com.google.cloud.dataflow.worker.repackaged.com.google.protobuf.ByteString$Output.toByteString(ByteString.java:1006)
com.google.cloud.dataflow.worker.WindmillStateInternals$WindmillBag.persistDirectly(WindmillStateInternals.java:575)
com.google.cloud.dataflow.worker.WindmillStateInternals$SimpleWindmillState.persist(WindmillStateInternals.java:320)
com.google.cloud.dataflow.worker.WindmillStateInternals$WindmillCombiningState.persist(WindmillStateInternals.java:951)
com.google.cloud.dataflow.worker.WindmillStateInternals.persist(WindmillStateInternals.java:216)
com.google.cloud.dataflow.worker.StreamingModeExecutionContext$StepContext.flushState(StreamingModeExecutionContext.java:513)
com.google.cloud.dataflow.worker.StreamingModeExecutionContext.flushState(StreamingModeExecutionContext.java:363)
com.google.cloud.dataflow.worker.StreamingDataflowWorker.process(StreamingDataflowWorker.java:1000)
com.google.cloud.dataflow.worker.StreamingDataflowWorker.access$800(StreamingDataflowWorker.java:133)
com.google.cloud.dataflow.worker.StreamingDataflowWorker$7.run(StreamingDataflowWorker.java:771)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)