Tags (durch Leerzeichen getrennt): Druid Springboot Start Autoconfig
Hintergrund
Entdeckungs- und Analyseprozess
Zusammenfassung
Ich habe kürzlich die Verwendung von Alibaba Druid zufällig entdeckt Ein kleiner Fehler beim Verbinden mehrerer Datenquellen. Ich habe ein Github-Problem eingereicht und es wurde offiziell behoben. Problemadresse:
Das von uns verwendete Java-Entwicklungsframework ist gekapselt. Die Unterstützung von Datenquellen durch das Framework basiert auf der Master- und Slave-Architektur, d.
Wir sind gerade dabei, .net in Java umzuwandeln. In besonderen Fällen muss das neue Java-System eine Verbindung zu zwei Datenquellen herstellen. Die MySQL-Datenquelle ist jedoch standardmäßig verbunden Fragen Sie die SQLServer-Datenquelle ab, um einige Kompatibilitätsdaten zu erhalten.
Bei der Konfiguration der zweiten Datenquelle meldet die Systemlast also einen Fehler.
Wir verwenden das Springboot-Framework und die Datenquellenkonfiguration wird basierend auf Springboot-Eigenschaften konfiguriert. Verwenden Sie dann die Konfiguration, um automatische Druid-Daasource-Beans zu erstellen. Das scheint kein Problem zu sein.
@Bean(name = "dataSource") @ConfigurationProperties(prefix = "ecommon.order.druid") public DataSource getOrderDataSource() { return new DruidDataSource(); }
Wenn es sich nicht um Springboot handelt, initialisieren Sie normalerweise alle Eigenschaften selbst. Laden Sie die Konfiguration aus der Konfigurationsdatei und legen Sie die DruidDataSource-Bean manuell fest.
Ich habe nicht viel darüber nachgedacht und es einfach so verwendet. Beim Start wurde jedoch ein Fehler beim Initialisieren der Bean gemeldet.
'maxEvictableIdleTimeMillis' hat eine Ausnahme ausgelöst; die verschachtelte Ausnahme ist java.lang.IllegalArgumentException: maxEvictableIdleTimeMillis muss größer sein als minEvictableIdleTimeMillis
Bedeutet wahrscheinlich, dass die maximale Überlebenszeit von 'maxEvictableIdleTimeMillis' sein muss größer als die Mindestlebensdauer von „minEvictableIdleTimeMillis“.
Die erste Reaktion muss sein, dass die Konfiguration falsch ist, überprüfen Sie die Konfiguration.
##一个连接在池中最小生存的时间(ms) ecommon.order.druid.minEvictableIdleTimeMillis=300000 ##一个连接在池中最大生存的时间(ms) ecommon.order.druid.maxEvictableIdleTimeMillis=600000
Es scheint korrekt zu sein, und dann tritt beim Debuggen das gleiche Problem auf. Die Reihenfolge der Attribute „minEvictableIdleTimeMillis“ und „maxEvictableIdleTimeMillis“ scheint in Ordnung zu sein. Nachdem ich es ausprobiert hatte, vertauschte ich die Reihenfolge der beiden Attribute, aber das Problem trat immer noch auf.
Blindzustand~_~.
Ich finde, dass dieses Problem etwas seltsam ist. Da die Zeit drängt, finde ich direkt die Stelle, an der der Fehler gemeldet wird, und verfolge den Quellcode.
Gehen Sie zur Github Search Alibaba Druid-Homepage, klonen Sie sie direkt und suchen Sie den Speicherort der Fehlermeldung.
Es gibt zwei Stellen, an denen diese Ausnahme während der globalen Suche ausgelöst wird.
1: init-Methode
public void init() throws SQLException { if (maxEvictableIdleTimeMillis < minEvictableIdleTimeMillis) { throw new SQLException("maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis"); }
Der besseren Lesbarkeit halber habe ich den Code in init gelöscht, der für die Analyse des Problems unbrauchbar ist.
Zwei: setMaxEvictableIdleTimeMillis-Methode
public void setMaxEvictableIdleTimeMillis(long maxEvictableIdleTimeMillis) { if (maxEvictableIdleTimeMillis < 1000 * 30) { LOG.error("maxEvictableIdleTimeMillis should be greater than 30000"); } if (maxEvictableIdleTimeMillis < minEvictableIdleTimeMillis) { throw new IllegalArgumentException("maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis"); } this.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis; }
Die Logik dieser beiden Methoden ist relativ einfach. Die Werte dieser beiden Bean-Attribute werden während der Initialisierung überprüft. setMaxEvictableIdleTimeMillis, es gibt eine Prüfung beim Festlegen der maximalen Überlebenszeit. Wenn Ihre maximale Überlebenszeit kürzer als die minimale Überlebenszeit ist, wird direkt ein Fehler gemeldet.
Setzen Sie also einfach Haltepunkte an diesen beiden Stellen, debuggen Sie dann und wissen Sie im Grunde, wo das Problem liegt, indem Sie die Werte der Variablen verfolgen.
Beim Debuggen habe ich festgestellt, dass die direkte Verwendung der Datenquelle mit new DruidDataSource() nicht zur Init-Methode führt. Sie betreten nicht den Ort, an dem der Fehler ausgelöst wird. Es scheint, dass mein Codepfad diese Prüfung nicht generieren sollte. Fahren Sie mit der Ausführung fort und sehen Sie, was mit der setMaxEvictableIdleTimeMillis-Methode passiert.
Beim Ausführen der setMaxEvictableIdleTimeMillis-Methode ist der Wert des minEvictableIdleTimeMillis-Attributs 1800000.
Schauen Sie, woher dieser Wert kommt.
protected volatile long minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L;
Die Eigenschaft minEvictableIdleTimeMillis hat einen Standardwert. Die Einheit ist ms (Millisekunde), daher beträgt der Standardwert hier 30 m (Minute) Minuten.
Wir haben 600000 ms konfiguriert, es ist also kleiner als 1800000. Aber das ist seltsam, wir haben den Parameter minEvictableIdleTimeMillis eindeutig festgelegt. Warum hat es nicht funktioniert? Ich dachte sofort, es sei ein Sequenzproblem.
Fahren Sie dann mit dem Debuggen fort und umgehen Sie zunächst diese Prüfung, um festzustellen, ob die Methode setMinEvictableIdleTimeMillis nach der Methode setMaxEvictableIdleTimeMillis ausgeführt wird, was dazu führt, dass diese Prüfung mit der Konfigurationsreihenfolge in Konflikt steht.
Nach dem Debuggen ist dies tatsächlich das Problem. Dann war ich neugierig, wie das Framework, das wir jetzt verwenden, uns dabei hilft, Druid zu kapseln. Durch einen Blick auf den Quellcode des Frameworks ist darin eine Hashcode-Sortierung enthalten, die dieses Problem löst. (Natürlich, ein erfahrener Fahrer und ein Meister) Ich werde hier nicht auf Details eingehen.
Wenn wir dieses Problem lösen, ist es eigentlich immer noch sehr einfach zu wissen, wie wir das Problem umgehen können.
Erstens: Holen Sie sich zuerst die konfigurierten minEvictableIdleTimeMillis und maxEvictableIdleTimeMillis in
@Data @EqualsAndHashCode @ConfigurationProperties(prefix = "ecommon.order.druid") public class SqlServerDruidConfig { private Long minEvictableIdleTimeMillis; private Long maxEvictableIdleTimeMillis; }
Zweitens: Legen Sie diese beiden Eigenschaften zuerst selbst fest, und bei der Springboot-Autokonfiguration treten keine Fehler auf
@Autowired private SqlServerDruidConfig druidConfig; @Bean(name = "dataSource") @ConfigurationProperties(prefix = "ecommon.order.druid") public DataSource getOrderDataSource() { DruidDataSource dataSource = new DruidDataSource(); /**setMinEvictableIdleTimeMillis需要先设置*/ dataSource.setMinEvictableIdleTimeMillis(druidConfig.getMinEvictableIdleTimeMillis()); dataSource.setMaxEvictableIdleTimeMillis(druidConfig.getMaxEvictableIdleTimeMillis()); return dataSource; } @Bean public SqlServerDruidConfig getDruidConfig() { return new SqlServerDruidConfig(); }
Die Analyse des Problems endet hier. Dieser kleine Fehler wurde von Alibaba Druid behoben.
Wenn Sie daran interessiert sind, wie Sie das Problem beheben können, sehen Sie sich bitte den Druid-Code zur Autoconfiger-Korrektur an:
Plötzlich können Sie verstehen, dass Sie bereits von den Vorteilen von Open Source profitiert haben. Sie können daran teilnehmen, es gemeinsam zu nutzen, Probleme gemeinsam zu entdecken und Fehler gemeinsam zu beheben. Dies könnte der zentrale technische Wert hinter hervorragenden Kunstwerken wie Linux und Git sein.
Das obige ist der detaillierte Inhalt vonProbleme bei der Verwendung von Alibaba Druid zum Verbinden mehrerer Datenquellen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!