运行 带有 Cloud Dataflow 的外部库

Running external library with Cloud Dataflow

我正在尝试 运行 使用 Cloud Dataflow 的一些外部共享库函数,类似于此处所述:Running external libraries with Cloud Dataflow for grid-computing workloads

根据方法,我有一对个问题。

文章mentioned earlier中有如下一段话:

In the case of making a call to an external library, you need to do this step manually for that library. The approach is to:

  • Store the code (along with versioning information) in Cloud Storage, this removes any concerns about throughput if running 10,000s of cores in the flow.
  • In the @beginBundle [sic] method, create a synchronized block to check if the file is available on the local resource. If not, use the Cloud Storage client library to pull the file across.

然而,对于我的 Java 包,我只是将库 .so 文件放入 src/main/resource/linux-x86-64 目录并按以下方式调用库函数 (stripped为简洁起见,尽量减少):

import com.sun.jna.Library;
import com.sun.jna.Native;
import org.apache.beam.sdk.transforms.DoFn;
import org.apache.beam.sdk.values.KV;

public class HostLookupPipeline {

  public interface LookupLibrary extends Library {
    String Lookup(String domain);
  }

  static class LookupFn extends DoFn<String, KV<String, String>> {
    private static LookupLibrary lookup;

    @StartBundle
    public void startBundle() {
      // src/main/resource/linux-x86-64/liblookup.so
      lookup = Native.loadLibrary("lookup", LookupLibrary.class);
    }

    @ProcessElement
    public void processElement(ProcessContext c) {
      String domain = c.element();
      String results = lookup.Lookup(domain);
      if (results != null) {
        c.output(KV.of(domain, results));
      }
    }
  }
}

这种方法是否被认为是可以接受的,或者从 JAR 中提取 .so 文件与从 GCS 下载相比性能较差?如果没有,我应该在下载后将文件放在哪里以供 Cloud Dataflow 工作人员访问?

我注意到调用外部库函数的转换工作得相当慢 — 大约 90 elements/s — 使用 15 个云数据流工作器(自动缩放,默认最大工作器).如果我的粗略计算是正确的,它应该快两倍。我想那是因为我为每个元素调用了外部库函数。

当运行 Java时,是否有任何提高外部库性能的最佳实践?

该博客 post 中的指导略有不正确 - 放置初始化代码的更好位置是 @Setup 方法,而不是 @StartBundle

@Setup 被调用以在将执行它的每个工作线程的每个线程中初始化 DoFn 的实例。这是繁重的设置代码的预期位置。它的对应物是 @Teardown.

@StartBundle@FinishBundle 的粒度要细得多:per bundle,这是一个相当低级的概念,我相信唯一常见的合法用于将成批元素写入外部服务:然后通常在 @StartBundle 中初始化下一批并在 @FinishBundle 中刷新它。

通常,要调试性能,请尝试将日志记录添加到您的 DoFn 的方法中,看看调用需要多少毫秒以及与您的预期相比如何。如果您遇到困难,请在问题中包含 Dataflow 作业 ID,工程师会查看它。