JVM 在 java dataflow-sdk 1.9.1 和 hbase 1.0.0 退出时挂起(但不是以前的 hbase 库)

JVM hangs on exit with java dataflow-sdk 1.9.1 and hbase 1.0.0 (but not with previous hbase libraries)

我们大量使用Dataflow和Bigtable,最近遇到了一个奇怪的问题。

使用 Dataflow SDK 1.9.1 和 bigtable-hbase-dataflow 1.0.0,我们读取 Bigtable 的 Java 代码运行得非常好(即,数据流管道正常成功)但 JVM 似乎挂在退出.我们在多台本地机器 (OS X) 和 GCP VM 上尝试过它,它总是在退出时挂起。 如果我们在 main 方法的末尾添加 System.exit(0),幸运的是它正常终止,所以我们可以通过这种方式解决问题,但我们无法弄清楚为什么会这样。

当我们尝试将 Dataflow SDK 1.9.1 与其他 hbase 版本(具体来说,0.9.7.1、1.0.0-pre1 和 1.0.0-pre4)结合使用时,这个问题就消失了。

至于 Java 代码(对于数据流管道),它看起来像下面这样(我们简化了多次重现此错误的事情,无论扫描作业 returns 是否为空都会发生这种情况是否收藏)。

// ... some Dataflow pipeline options are set prior to this step.
Pipeline pipeline = Pipeline.create(options);
Scan scan = new Scan();
scan.setCacheBlocks(false).setMaxVersions(1); // Disable caching and read only the latest cell.
scan.addFamily(Bytes.toBytes("x")); // Read only 'x' column family.
scan.setStartRow(Bytes.toBytes("prefix1")).setStopRow(Bytes.toBytes("prefix2"));
try {
  long tsBegin = DateTime.parse("2018-03-01T00:00:00Z").getMillis();
  long tsEnd = DateTime.parse("2018-03-01T01:00:00Z").getMillis();
  scan.setTimeRange(tsBegin, tsEnd);
} catch (IOException e) {
  // If unable to set time range, do not run this job as it may read the entire UPT and affect production.
  LOG.error("Unable to set Time Range for Bt Scan object.", e);
  return;
}

CloudBigtableScanConfiguration btConfig = new 
CloudBigtableScanConfiguration.Builder()
                              .withProjectId("projectId")
                              .withInstanceId("instanceId")
                              .withTableId("tableId")
                              .withScan(scan)
                              .build();
pipeline.apply(Read.from(CloudBigtableIO.read(btConfig)));
System.out.println("before run");
PipelineResult pipelineResult = pipeline.run();
System.out.println("after run");
// This hangs on exit.
// System.exit(0); would work fine and exit.
// throw new RuntimeException("test re"); this will throw an exception, but will hang (provided that System.exit() above is not present).

```

这是我们在 gradle 依赖项中使用的内容。 同样,对于 bigtable-hbase-dafatflow 库的先前(但已弃用)版本,我们没有看到此问题。 compile 'com.google.cloud.dataflow:google-cloud-dataflow-java-sdk-all:1.9.1' compile 'com.google.cloud.bigtable:bigtable-hbase-dataflow:1.0.0'

我想知道 Bigtable 或 Dataflow 团队是否可以在他们的末端重现此错误(无论扫描结果如何,只要读取任何 Bigtable instance/table 都会给我们这个错误),因为 hbase 中似乎有些东西1.0.0(不在以前的版本中)可能是导致问题的原因。 我们使用 Java 1.8.0 (0_151) 和 Gradle 版本 3.1 和 4.3.1 来重现错误。

为有类似问题的人更新:

正如下面所指出的,在进行线程转储之后,我们发现了以下内容,其中包括 (grep lmax):

"pool-4-thread-1" #23 prio=5 os_prio=31 tid=0x00007fd8d4d88000 nid=0x150f runnable [0x000070000b016000]
   java.lang.Thread.State: TIMED_WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:338)
    at com.google.bigtable.repackaged.com.lmax.disruptor.SleepingWaitStrategy.applyWaitMethod(SleepingWaitStrategy.java:82)
    at com.google.bigtable.repackaged.com.lmax.disruptor.SleepingWaitStrategy.waitFor(SleepingWaitStrategy.java:55)
    at com.google.bigtable.repackaged.com.lmax.disruptor.ProcessingSequenceBarrier.waitFor(ProcessingSequenceBarrier.java:56)
    at com.google.bigtable.repackaged.com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:124)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

这是基于 Cloud Bigtable 客户端在 v 1.0.0 中对 opencensus stackdriver 的依赖而引入的问题。如果您想确认这一点,可以进行线程转储;如果确实如此,您会看到带有 lmax disruptor 的条目。

我建议您升级到 1.2.0 并使用 Beam / Dataflow v2。如果做不到,请降级到 1.0.0-pre4。