Druid 버전 1.2.12 출시, 새로운 연결 풀 기본 구성 connectTimeout 및 SocketTimeout 자세한 설명

새로운 버전의 특징은 다음과 같습니다

이 버전의 연결 풀은 기본적으로 connectTimeout 및 SocketTimeout 구성을 추가하고 SQL 구문 분석기를 향상시킵니다.

  1. 연결 풀 DruidDataSource는 새로운 구성인 connectTimeout과 SocketTimeout을 지원하며 둘 다 10초입니다. 이 기본값은 네트워크 패킷 손실로 인해 연결 풀이 연결을 생성하지 못하는 것을 줄여줍니다.
  2. 연결 풀을 닫을지 여부를 결정할 때 잘못된 논리 문제 수정 DruidDataSource#handleFatalError 메서드 #4724
  3. StatFilter 통계 명령문이 SQL 실행 시 첫 번째 SQL만 기록하는 문제 수정 #4921
  4. 잘못된 ParameterizedOutputVisitorUtils#restore 결과 문제 수정 #4532
  5. SQL Parser는 PolarDB-X #4927 에 대한 지원을 강화합니다.
  6. SQL Parser는 Oceanbase #4833 에 대한 지원을 강화합니다.
  7. SQL Parser는 MySQL #4916 #4817 #4825 에 대한 지원을 강화합니다.
  8. SQL Parser는 Clickhouse #4833 #4881 에 대한 지원을 강화합니다.
  9. SQL Parser는 DB2 #4838 에 대한 지원을 강화합니다.
  10. SQL Parser는 Oracle에 대한 지원을 강화합니다.
연결 풀 connectTimeout 구성

다음 코드가 소스 코드 com.alibaba.druid.pool.DruidAbstractDataSource#createPhysicalConnection() 메서드에 추가되었습니다.

        if (connectTimeout > 0) {
    
    
            if (isMySql) {
    
    
                physicalConnectProperties.put("connectTimeout", connectTimeout);
            } else if (isOracle) {
    
    
                physicalConnectProperties.put("oracle.net.CONNECT_TIMEOUT", connectTimeout);
            } else if (driver != null && "org.postgresql.Driver".equals(driver.getClass().getName())) {
    
    
                physicalConnectProperties.put("loginTimeout", connectTimeout);
                physicalConnectProperties.put("socketTimeout", connectTimeout);
            }
        }

연결 시 적용되는 mysql, oracle 및 postgresql 데이터베이스 드라이버에 대한 연결 시간 제한을 구성합니다. 기본값: 10000ms

연결 풀 소켓 시간 초과 구성

데이터베이스가 다운되거나 네트워크가 이창에 있는 경우 jdbc의 소켓 타임아웃이 필요하지만 TCP/IP 구조상 소켓에서는 네트워크 오류를 감지할 수 있는 방법이 없으므로 애플리케이션에서는 데이터베이스에 대한 연결이 끊겼는지 여부를 감지할 수 없습니다. . 소켓 시간 초과가 없으면 애플리케이션은 데이터베이스가 결과를 반환할 때까지 기다립니다. 연결 끊김 현상을 방지하기 위해서는 소켓에서 타임아웃을 설정해야 하는데, 타임아웃을 설정하면 네트워크 오류를 기다리는 것을 방지하고 실패 시간을 단축할 수 있습니다.

소스 코드 com.alibaba.druid.pool.DruidAbstractDataSource#createPhysicalConnection()에 다음 코드를 추가합니다.

            if (socketTimeout > 0 && !netTimeoutError) {
    
    
                try {
    
    
                  //默认sql执行10s
                    conn.setNetworkTimeout(netTimeoutExecutor, socketTimeout);
                } catch (SQLFeatureNotSupportedException | AbstractMethodError e) {
    
    
                    netTimeoutError = true;
                } catch (Exception ignored) {
    
    
                    // ignored
                }
            }

netTimeoutExecutor는 동기식 실행기의 인스턴스 객체입니다.

    class SynchronousExecutor implements Executor {
    
    
        @Override
        public void execute(Runnable command) {
    
    
            try {
    
    
                command.run();
            } catch (AbstractMethodError error) {
    
    
                netTimeoutError = true;
            } catch (Exception ignored) {
    
    
                if (LOG.isDebugEnabled()) {
    
    
                    LOG.debug("failed to execute command " + command);
                }
            }
        }
    }

동기 실행기는 com.alibaba.druid.pool.DruidDataSource#init 메소드에서 초기화됩니다.

명령의 구체적인 구현은 com.mysql.cj.jdbc.ConnectionImpl.NetworkTimeoutSetter(mysql의 특정 구현)입니다.

    private static class NetworkTimeoutSetter implements Runnable {
    
    
        private final WeakReference<JdbcConnection> connRef;
        private final int milliseconds;

        public NetworkTimeoutSetter(JdbcConnection conn, int milliseconds) {
    
    
            this.connRef = new WeakReference(conn);
            this.milliseconds = milliseconds;
        }

        public void run() {
    
    
            JdbcConnection conn = (JdbcConnection)this.connRef.get();
            if (conn != null) {
    
    
                synchronized(conn.getConnectionMutex()) {
    
    
                    ((NativeSession)conn.getSession()).setSocketTimeout(this.milliseconds);
                }
            }

        }
    }
연결 풀 쿼리 시간 초과, 트랜잭션 쿼리 시간 초과 구성
  • query-timeout: JDBC 드라이버가 명령문을 실행하는 데 걸리는 시간(초)을 설정합니다. 제한을 초과하면 SQLTimeoutException이 발생합니다. 기본값: 0. 단위: 초 단위 제한 없음.
  • transaction-query-timeout: JDBC 드라이버가 N개의 문 문을 실행하는 데 필요한 초 수를 설정합니다(트랜잭션 모드). 제한을 초과하면 SQLTimeoutException이 발생합니다. 기본값: 0 단위: 초 단위 제한 없음

구체적인 구현 코드는 com.alibaba.druid.pool.DruidAbstractDataSource#initStatement에서 다음과 같습니다.

    void initStatement(DruidPooledConnection conn, Statement stmt) throws SQLException {
    
    
        boolean transaction = !conn.getConnectionHolder().underlyingAutoCommit;

        int queryTimeout = transaction ? getTransactionQueryTimeout() : getQueryTimeout();

        if (queryTimeout > 0) {
    
    
            stmt.setQueryTimeout(queryTimeout);
        }
    }

    public int getTransactionQueryTimeout() {
    
    
        if (transactionQueryTimeout <= 0) {
    
    
            return queryTimeout;
        }

        return transactionQueryTimeout;
    }

    public int getQueryTimeout() {
    
    
        return queryTimeout;
    }
요약하다

위의 시간 설정을 보면 약간 혼란스러울 수 있습니다. 이렇게 많은 시간을 어떻게 구별할 수 있습니까? 먼저 인터넷에 있는 사진을 살펴보겠습니다.

타임아웃 시간 구분

상위 레벨 타임아웃은 하위 레벨 타임아웃에 따라 달라지며, 하위 레벨 타임아웃이 올바른 경우에만 상위 레벨 타임아웃이 정상성을 보장할 수 있습니다. 유효하지 않은. 명령문 시간 초과는 네트워크 연결 실패 시 시간 초과를 처리할 수 없으며 명령문의 작업 시간을 제한할 수 있습니다. 네트워크 연결 실패 시 시간 초과는 JDBC에서 처리해야 합니다. JDBC의 소켓 시간 초과는 소켓 시간 초과의 영향을 받습니다. 운영 체제 설정.

GitHub 주소: https://github.com/mingyang66/spring-parent

추천

출처blog.csdn.net/yaomingyang/article/details/126901144