Heim >Java >javaLernprogramm >So lösen Sie das Problem, dass der Springboot-Druiden-Datenbankverbindungspool nach einem Verbindungsfehler immer wieder eine Verbindung herstellt
Als ich meine persönliche Alibaba Cloud-Testmaschine verwendete und das Echtzeit-Ausgabeprotokoll ansah, stellte ich fest, dass der Server nach dem Ausfall der Datenbankverbindung immer wieder versuchte, die Verbindung wiederherzustellen. Zunächst ging man davon aus, dass das System ständig angegriffen wurde, doch nach dem Neustart des Dienstes kam es nicht mehr zu einer ständigen Neuverbindung. Sehen Sie sich das folgende Ausgabeprotokoll an:
2022-02-09 11:04:58.896 ERROR 16876 --- [eate-1550991149] com.alibaba.druid.pool.DruidDataSource : create Connection SQLException, URL: jdbc:mysql: // 47.98.67,98:1234/test?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC, errorCode 1045, state 28000
java.sql.SQLException: Zugriff verweigert für Benutzer 'root'@'113.90.123.76' (using Passwort: JA)
bei com.mysql.cj.jdbc.Exceptions.SQLError.createSQLException(SQLError.java:129) ~[mysql-connector-java-8.0.16.jar:8.0.16]
bei com.mysql. cj.jdbc.Exceptions.SQLError.createSQLException(SQLError.java:97) ~[mysql-connector-java-8.0.16.jar:8.0.16]
bei com.mysql.cj.jdbc.Exceptions.SQLExceptionsMapping.translateException( SQLExceptionsMapping.java:122) ~[mysql-connector-java-8.0.16.jar:8.0.16]
bei com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:835) ~[mysql-connector- java- 8.0.16.jar:8.0.16]
unter com.mysql.cj.jdbc.ConnectionImpl.7e51f00a783d7eb8f68358439dee7daf(ConnectionImpl.java:455) ~[mysql-connector-java-8.0.16.jar:8.0 .16 ]
bei com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:240) ~[mysql-connector-java-8.0.16.jar:8.0.16]
bei com.mysql.cj.jdbc .NonRegisteringDriver .connect(NonRegisteringDriver.java:199) ~[mysql-connector-java-8.0.16.jar:8.0.16]
bei com.alibaba.druid.filter.FilterChainImpl.connection_connect(FilterChainImpl.java:156) ~ [druid -1.1.10.jar:1.1.10]
unter com.alibaba.druid.filter.stat.StatFilter.connection_connect(StatFilter.java:218) ~[druid-1.1.10.jar:1.1.10]
unter com.alibaba.druid.filter.FilterChainImpl.connection_connect(FilterChainImpl.java:150) ~[druid-1.1.10.jar:1.1.10]
unter com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java :1560 ) ~[druid-1.1.10.jar:1.1.10]
bei com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1623) ~[druid-1.1.10.jar:1.1.10 ]
unter com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2468) ~[druid-1.1.10.jar:1.1.10]
Beachten Sie, dass es immer eine Eingabeaufforderung für den Druiden gibt Datenbankverbindungspool oben, hier dachte ich, es könnte ein Problem mit dem Druiden-Verbindungspool sein, und nach dem Entfernen der Druiden-Maven-Abhängigkeit wird es in der Anforderungsschnittstelle kein Problem mit der erneuten Verbindung geben.
Suchen Sie die letzte Zeile von DruidDataSource.java:2468 im Quellcode. Navigieren Sie zum Quellcode von CreateConnectionThread:
public class CreateConnectionThread extends Thread { public CreateConnectionThread(String name){ super(name); this.setDaemon(true); } public void run() { initedLatch.countDown(); long lastDiscardCount = 0; int errorCount = 0; for (;;) { // addLast try { lock.lockInterruptibly(); } catch (InterruptedException e2) { break; } long discardCount = DruidDataSource.this.discardCount; boolean discardChanged = discardCount - lastDiscardCount > 0; lastDiscardCount = discardCount; try { boolean emptyWait = true; if (createError != null && poolingCount == 0 && !discardChanged) { emptyWait = false; } if (emptyWait && asyncInit && createCount < initialSize) { emptyWait = false; } if (emptyWait) { // 必须存在线程等待,才创建连接 if (poolingCount >= notEmptyWaitThreadCount // && !(keepAlive && activeCount + poolingCount < minIdle)) { empty.await(); } // 防止创建超过maxActive数量的连接 if (activeCount + poolingCount >= maxActive) { empty.await(); continue; } } } catch (InterruptedException e) { lastCreateError = e; lastErrorTimeMillis = System.currentTimeMillis(); if (!closing) { LOG.error("create connection Thread Interrupted, url: " + jdbcUrl, e); } break; } finally { lock.unlock(); } PhysicalConnectionInfo connection = null; try { connection = createPhysicalConnection(); setFailContinuous(false); } catch (SQLException e) { LOG.error("create connection SQLException, url: " + jdbcUrl + ", errorCode " + e.getErrorCode() + ", state " + e.getSQLState(), e); errorCount++; if (errorCount > connectionErrorRetryAttempts && timeBetweenConnectErrorMillis > 0) { // fail over retry attempts setFailContinuous(true); if (failFast) { lock.lock(); try { notEmpty.signalAll(); } finally { lock.unlock(); } } if (breakAfterAcquireFailure) { break; } try { Thread.sleep(timeBetweenConnectErrorMillis); } catch (InterruptedException interruptEx) { break; } } } catch (RuntimeException e) { LOG.error("create connection RuntimeException", e); setFailContinuous(true); continue; } catch (Error e) { LOG.error("create connection Error", e); setFailContinuous(true); break; } if (connection == null) { continue; } boolean result = put(connection); if (!result) { JdbcUtils.close(connection.getPhysicalConnection()); LOG.info("put physical connection to pool failed."); } errorCount = 0; // reset errorCount } } }ist eine Multithread-Klasse und in der Ausführungsmethode wird eine unbegrenzte for-Schleife für (;;) {} eingerichtet, und die Informationen zum Protokollfehlerort lauten:
connection = createPhysicalConnection();Wenn die Bedingungen erfüllt sind, errorCount > ConnectionErrorRetryAttempts && timeBetweenConnectErrorMillis > ; 0, die erneute Verbindung wird erneut versucht. Bedeutung: errorCount Die Anzahl der Fehler ist Null, wenn die Verbindung fehlschlägt connectionErrorRetryAttempts
Die Anzahl der Verbindungsfehler-Wiederholungsversuche, der Standardwert ist 1.
protected int connectionErrorRetryAttempts = 1;timeBetweenConnectErrorMillis
Verbindungsintervallzeit in Millisekunden. Der Standardwert ist 500.
protected volatile long timeBetweenConnectErrorMillis = DEFAULT_TIME_BETWEEN_CONNECT_ERROR_MILLIS; public static final long DEFAULT_TIME_BETWEEN_CONNECT_ERROR_MILLIS = 500;
Nachdem wir keine Verbindung zur Datenbank herstellen konnten, müssen wir einbrechen. Unter anderem ändert
if (breakAfterAcquireFailure) { break; }
„break-after-acquire-failure“ in „true“ und konfiguriert es wie folgt in der Datei „application.properties“:
spring.datasource.druid.break-after-acquire-failure=true
Wenn Sie mehrmals versuchen möchten, eine Verbindung herzustellen, müssen „connection-error-retry-attempts“ festgelegt werden. Wenn „errorCount“ größer als „connectionErrorRetryAttempts“ ist, wird die Bedingung eingegeben und die Schleife unterbrochen. Das Folgende ist die Konfiguration der application.properties-Datei:
spring.datasource.druid.connection-error-retry-attempts=3
Das obige ist der detaillierte Inhalt vonSo lösen Sie das Problem, dass der Springboot-Druiden-Datenbankverbindungspool nach einem Verbindungsfehler immer wieder eine Verbindung herstellt. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!