Java 为什么iterable操作会在Apache Beam函数中抛出错误?
我在一个Iterable Java集合上调用此函数,该集合由GroupByKey函数生成:Java 为什么iterable操作会在Apache Beam函数中抛出错误?,java,google-cloud-dataflow,apache-beam,google-cloud-pubsub,Java,Google Cloud Dataflow,Apache Beam,Google Cloud Pubsub,我在一个Iterable Java集合上调用此函数,该集合由GroupByKey函数生成: static class FindCompleteOrder extends DoFn<KV<String, Iterable<Order>>, Order> { String COMPLETE_EVENT_NAME = "COMPLETE"; @ProcessElement public void processElement(Process
static class FindCompleteOrder extends DoFn<KV<String, Iterable<Order>>, Order> {
String COMPLETE_EVENT_NAME = "COMPLETE";
@ProcessElement
public void processElement(ProcessContext c) {
Iterable<Order> orders = c.element().getValue();
boolean complete = false;
do {
try {
Order order = orders.iterator().next();
if (order.getEventName().equals(COMPLETE_EVENT_NAME)) {
complete = true;
order.setComplete(complete);
c.output(order);
}
} catch (Exception e) {
LOG.error(e.getMessage());
}
} while (complete == false && orders.iterator().hasNext());
}
}
该函数迭代订单列表,并输出与指定eventName属性匹配的第一个实例。如果找到顺序,或者迭代了整个集合,则循环结束
随机顺序实例在上游生成,并以2/秒的速率发布到发布/订阅实例,在那里它们由调用此函数的数据流实例使用。操作大约15分钟后,警告开始出现:
在没有输出或完成的情况下,处理卡在步骤查找顺序中至少15m00秒
由于iterator.hasNext或iterator.next中的偶发故障而发出警告。最终结果是整个管道暂停。关联的管道级从不发出输出
用标准for loop替换loop解决了这个问题。然而,这样做意味着迭代整个集合;我更愿意在找到合适的元素时结束循环,因此执行do while循环
我很想知道迭代器操作为什么会导致管道暂停。FAIA Iterable集合是不可变的,并且没有被其他进程修改
我在Windows上运行Java 8和Apache Beam 2.6。每次调用orders.iterator时,您都在创建一个新的迭代器,从第一个order开始。这意味着您在循环中一次又一次地处理相同的订单。如果有多个订单,您对hasNext的调用将始终为真。因此,如果您有多个订单,或者您的第一个订单没有设置完成,那么循环将永远运行,这就是您遇到超时的原因
相反,您应该调用迭代器一次,并存储迭代器而不是iterable,使用它来循环:
static class FindCompleteOrder extends DoFn<KV<String, Iterable<Order>>, Order> {
String COMPLETE_EVENT_NAME = "COMPLETE";
@ProcessElement
public void processElement(ProcessContext c) {
Iterator<Order> orders = c.element().getValue().iterator();
boolean complete = false;
do {
try {
Order order = orders.next();
if (order.getEventName().equals(COMPLETE_EVENT_NAME)) {
complete = true;
order.setComplete(complete);
c.output(order);
}
} catch (Exception e) {
LOG.error(e.getMessage());
}
} while (complete == false && orders.hasNext());
}
}