Google cloud platform 从bigtable读取数据时,数据流DoFn意外挂起

Google cloud platform 从bigtable读取数据时,数据流DoFn意外挂起,google-cloud-platform,google-cloud-dataflow,google-cloud-bigtable,Google Cloud Platform,Google Cloud Dataflow,Google Cloud Bigtable,我们的数据流管道有一个DoFn,它使用hbase multiget客户端api从bigtable读取数据。这似乎会导致数据流在以下堆栈中随机暂停: 处理卡在步骤AttachStuff/BigtableAttacher中至少04H10M00秒,而不输出或完成状态过程 在sun.misc.Unsafe.park(本机方法) 位于java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 位于com.google.bigtable

我们的数据流管道有一个DoFn,它使用hbase multiget客户端api从bigtable读取数据。这似乎会导致数据流在以下堆栈中随机暂停:

处理卡在步骤AttachStuff/BigtableAttacher中至少04H10M00秒,而不输出或完成状态过程 在sun.misc.Unsafe.park(本机方法) 位于java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 位于com.google.bigtable.repackaged.com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:523) 在com.google.bigtable.repackaged.com.google.api.core.AbstractApiFuture.get(AbstractApiFuture.java:56)上 位于com.google.cloud.bigtable.hbase.BatchExecutor.batchCallback(BatchExecutor.java:276) 位于com.google.cloud.bigtable.hbase.BatchExecutor.batch(BatchExecutor.java:239) 位于com.google.cloud.bigtable.hbase.AbstractBigtableTable.get(AbstractBigtableTable.java:241) 请访问com.askscio.google.docbuilder.BigtableAnchorsAttacher.getAnchors(BigtableAnchorsAttacher.java:86) 位于com.askscio.google.docbuilder.BigtableAnchorsAttacher.process(BigtableAnchorsAttacher.java:129) 位于com.askscio.docbuilder.core.ScioDoFn.processHandling(ScioDoFn.java:39) 位于com.askscio.google.docbuilder.BigtableAnchorsAttacher$DoFnInvoker.invokeproceselement(未知源)

我们使用的是梁库2.12.0。DoFn初始化StartBundle中的bigtable连接

每个DoFn调用从bigtable中查找的键不超过10个

它的单集群、3个节点和SSD。存储利用率为2.2 GB,最大节点CPU利用率为13%,最大读/写速率为2000读/秒和1000写/秒

起始价:

bigtableConn = BigtableConfiguration.connect(
    config.getString(ConfigKeys.Google.PROJECT_ID),
    config.getString(ConfigKeys.Google.INSTANCE_ID)
);
fooTable = bigtableConn.getTable(TableName.valueOf(BigtableDocumentStore.FOO_TABLE_NAME));
过程:

List<Get> gets = Lists.newArrayList();
// keys are no more than 10
for (String s : keys) {
   Get get = new Get(Bytes.toBytes(s))
                     .addFamily(Bytes.toBytes(BigtableDocumentStore.FOO_COLUMN_FAMILY))
                        .setMaxVersions(1);
   gets.add(get);
}
Result[] results= fooTable.get(gets);

我建议将连接管理移动到@Setup&Teardown,并在使用多核工作人员时使用引用计数

Bigtable连接的重量非常重,每个进程都是单件的。BigtableConfiguration.connect()返回的HBase连接对象实际上包装了一个grpc通道池,每个cpu有2个通道,这非常昂贵

您有几个选项可以改进管道:

  • 将配置选项“google.bigtable.use.cached.data.channel.pool”设置为“true”,这将重用内部连接池

  • 在DoFn中执行以下操作:

    //实例变量
    静态对象连接锁=新对象();
    静态连接bigtableConn=null;
    //@设置
    已同步(连接锁定){
    if(numWorkers++==0){
    bigtableConn=BigtableConfiguration.connect(…);
    } 
    }
    //@Teardown
    已同步(连接锁定){
    如果(--numWorkers==0){
    bigtableConn.close();
    } 
    }
    

  • 请注意,startBundle应与finishBundle配对,而setup应与teardown配对。假设startBundle是按bundle调用的,而teardown是按DoFn实例调用的,那么您可能正在打开和关闭太多的bigtable连接?因此实际的startBundle代码如下所示。如果我们只在变量为null时创建连接,那么这种不匹配不应该导致连接泄漏,对吗类Foo{static Connection conn=null;@StartBundle public void StartBundle(StartBundleContext bundleContext)抛出异常{synchronized(Foo.class){if(conn==null){//create bigtable conn并将conn分配给该}}}}`好的,看起来不错。您是否(接近)超出了阅读限制?它看起来确实在等待读取完成。根据bigtable实例页面,我的3节点ssd群集可以每秒执行30000行。我检查了我的bigtable实例的最大读取速率是否为2000行/秒。您能否提供有关正在使用的客户端库版本的更多详细信息,即pom.xml中bigtable hbase beam的版本?
    fooTable.close();
    bigTableConn.close();