带有 JdbcIO 编写器的 ApacheBeam/DataFlow 运行器创建了太多连接

Posted

技术标签:

【中文标题】带有 JdbcIO 编写器的 ApacheBeam/DataFlow 运行器创建了太多连接【英文标题】:ApacheBeam/DataFlow runner with JdbcIO writer creates too many connections 【发布时间】:2019-09-23 08:28:56 【问题描述】:

我正在使用 GCP 云 SQL、mysql 实例并使用 JdbcIo 将数据从 DataFlow 管道写入 MySQL。

似乎DataFlow生成的连接太多,达到了DB限制(4000),即使我在连接池中指定,最大大小:1000

 ComboPooledDataSource dataSource = new ComboPooledDataSource();
 try 
       dataSource.setDriverClass("org.mysql.Driver");
      catch (PropertyVetoException e) 
            throw new RuntimeException("Failed set mysql driver",e);
     
       dataSource.setJdbcUrl("jdbc:mysql://google/live-data?cloudSqlInstance<INSTANCE_NAME>&socketFactory=com.google.cloud.sql.mysql.SocketFactory&useSSL=false&user=<USER>&password=<PASSWORD>");

       dataSource.setMaxPoolSize(1000);
       dataSource.setInitialPoolSize(1000);

此外,在仪表板中,我可以看到比查询更多的连接:

我的 pom.xml

 <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.4</version>
        </dependency>
        <dependency>
            <groupId>com.google.cloud.sql</groupId>
            <artifactId>mysql-socket-factory</artifactId>
            <version>1.0.13</version>
        </dependency>
        <dependency>
            <groupId>org.apache.beam</groupId>
            <artifactId>beam-sdks-java-io-jdbc</artifactId>
            <version>$beam.version</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

【问题讨论】:

【参考方案1】:

DataFlow 生成的连接太多,达到了 DB 限制(4000),即使我在连接池中指定,最大大小:1000

快速猜测是,由于 Dataflow 可以有多个运行器,每个运行器可能都有自己的连接池。这意味着每个池将有 1000 个单独的连接。这很可能比您实际使用的连接要多 - 请参阅 pool sizing 上的 HikariCP 的 wiki。

此外,在仪表板中,我可以看到比查询更多的连接:

由于您设置了setInitialPoolSize(1000),池不会根据需要延迟建立连接,而是在池初始化时创建 1000。从提供的示例中,您没有对连接寿命提供任何限制,因此这些连接可能会尽可能长时间地持续存在。

【讨论】:

是的,这似乎是因为连接池的许多实例。我将允许的连接数减少到 10 个,然后每个 DataFlow 工作人员创建自己的连接池,所有实例的总和仍然更低。 我还为每个工作人员创建了一个连接池实例,之前,我在 @SetUp 方法中为每个 ParDo 函数初始化了连接池。我将其更改为每个工作人员(单例)初始化一次

以上是关于带有 JdbcIO 编写器的 ApacheBeam/DataFlow 运行器创建了太多连接的主要内容,如果未能解决你的问题,请参考以下文章

使用 Apache Beam 从数据库中读取批量数据

从 Dataflow 作业连接到 Cloud SQL

如何为带有 $ 符号的 Class 的元素编写选择器

BigQueryIO - 为每个项目写入两个表

增量加载和 BigQuery

无法理解 apollo-client 中解析器的使用