【问题标题】:Redshift server closes connection after 10 minutesRedshift 服务器在 10 分钟后关闭连接
【发布时间】:2018-05-07 11:01:24
【问题描述】:

我有一个运行大约需要 20 分钟的语句,格式为:

create table new_table diststyle key distkey(column1) sortkey(column2) 
as (select ....);

当我使用 SQL IDE 或 psql 命令行客户端运行它时,该语句会成功执行,但是当我从我的 Java 程序运行它时,服务器会在 10 分钟后关闭连接,但出现以下异常:

    org.springframework.jdbc.UncategorizedSQLException: StatementCallback; uncategorized SQLException for SQL [create table new_table diststyle key distkey(column1) sortkey(column2) as (select ....);]; 
SQL state [HY000]; error code [600001]; [Amazon](600001) The server closed the connection.; 
nested exception is java.sql.SQLException: [Amazon](600001) The server closed the connection.
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:84) ~[spring-jdbc-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) ~[spring-jdbc-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) ~[spring-jdbc-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:419) ~[spring-jdbc-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:538) ~[spring-jdbc-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at com.abc.mypackage.MyClass.myMethod(Myclass.java:123) [classes/:?]
Caused by: java.sql.SQLException: [Amazon](600001) The server closed the connection.
    at com.amazon.support.channels.TLSSocketChannel.read(Unknown Source) ~[?:?]
Caused by: com.amazon.support.exceptions.GeneralException: [Amazon](600001) The server closed the connection.
    at com.amazon.support.channels.TLSSocketChannel.read(Unknown Source) ~[?:?]

我正在使用 org.apache.commons.dbcp2.BasicDataSource 创建连接。我尝试通过 defaultQueryTimeout、maxConnLifetimeMillis 和 socketTimeout 延长超时时间,但无济于事。服务器在同样的 10 分钟后继续关闭连接。

    dataSource = new BasicDataSource();
    dataSource.setUsername(dbUser);
    dataSource.setPassword(dbPassword);
    dataSource.setUrl(dbUrl);
    dataSource.setDefaultAutoCommit(true);
    dataSource.setTestOnBorrow(true);
    dataSource.setTestOnReturn(true);
    dataSource.setDriverClassName("com.amazon.redshift.jdbc41.Driver");
    dataSource.setDefaultQueryTimeout(7200);
    dataSource.setMaxConnLifetimeMillis(7200000);
    dataSource.addConnectionProperty("socketTimeout", "7200");

如何让连接保持更长时间?

附:我在建立连接和运行不到 10 分钟即可完成的查询时没有任何问题。

【问题讨论】:

    标签: java jdbc amazon-redshift


    【解决方案1】:

    您可能希望延长套接字超时时间。

    目前只有7200ms:

    dataSource.addConnectionProperty("socketTimeout", "7200");
    

    【讨论】:

    • driver configuration options list 中所述,socketTimeout 属性的读取时间为几秒钟。我尝试将值设置为 7200 * 1000,以防万一,但由于某种原因它几乎立即超时。
    【解决方案2】:

    检查 Redshift 服务器是否有一个工作负载管理策略在 10 分钟后超时查询。 您的 java 代码可能正在设置此策略

    【讨论】:

      【解决方案3】:

      在连接到 redshift 集群时,您需要将 tcpKeepAlive 时间设置为 1 分钟或更短。

                     Properties props = new Properties();
                     props.setProperty("user", user);
                     props.setProperty("password", password);
                     props.setProperty("tcpKeepAlive", "true");
                     props.setProperty("TCPKeepAliveMinutes", "1");
                     DriverManager.getConnection("jdbc:redshift://"+endpoint+":"
                     +port+"/"+database, props);
      

      【讨论】:

        【解决方案4】:

        在这里,我可以通过在 BasicDataSourceConnection 上编写包装器来使其工作,以每隔几分钟轮询与 isValid(int) 的活动连接(任何频率超过每 10 分钟一次的工作)。事后看来,BasicDataSource 上的大多数与超时相关的属性似乎都适用于池中但未使用的连接。 setDefaultQueryTimeouttcpKeepAlive + TCPKeepAliveMinutes 不起作用。

        附:我解决这个问题已经有一段时间了,现在我没有包装器的代码。以下是包装器的简要说明。

        WrappedConnection 类在其构造函数中采用Connection 对象(conn)和TimerTask 对象(timerTask),并通过简单地调用conn 中的方法来实现Connection 接口。只要连接处于活动状态,timerTask 每隔几分钟就会调用一次this.isValid(100)WrappedConnection.close 停止 timerTask 然后调用 conn.close

        WrappedBasicDataSource 实现了DataSource 接口,将方法重定向到BasicDataSource 对象。 BasicDataSourceWrapper.getConnection 从上述BasicDataSource 获取连接,并使用该连接和新的TimerTask 对象生成WrappedConnection

        我可能错过了解释一些细节,但这就是它的要点。

        【讨论】:

          猜你喜欢
          • 2015-12-29
          • 2017-09-21
          • 2019-12-12
          • 2020-09-18
          • 2021-11-25
          • 1970-01-01
          • 2014-07-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多