Heim > Java > javaLernprogramm > Hauptteil

So lösen Sie das Problem, dass der Springboot-Druiden-Datenbankverbindungspool nach einem Verbindungsfehler immer wieder eine Verbindung herstellt

王林
Freigeben: 2023-05-21 11:28:25
nach vorne
3183 Leute haben es durchsucht

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.(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.

Der Grund für die Druid-Wiederverbindung

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
            }
        }
    }
Nach dem Login kopieren
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();
Nach dem Login kopieren

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;
Nach dem Login kopieren

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;
Nach dem Login kopieren

Nachdem wir keine Verbindung zur Datenbank herstellen konnten, müssen wir einbrechen. Unter anderem ändert

if (breakAfterAcquireFailure) {
     break;
}
Nach dem Login kopieren

„break-after-acquire-failure“ in „true“ und konfiguriert es wie folgt in der Datei „application.properties“:

spring.datasource.druid.break-after-acquire-failure=true
Nach dem Login kopieren

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
Nach dem Login kopieren

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!

Verwandte Etiketten:
Quelle:yisu.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage