Maison  >  Article  >  Java  >  Problèmes lors de l'utilisation d'Alibaba Druid pour connecter plusieurs sources de données

Problèmes lors de l'utilisation d'Alibaba Druid pour connecter plusieurs sources de données

零下一度
零下一度original
2017-07-21 17:27:327333parcourir

Problèmes lors de l'utilisation d'Alibaba Druid pour connecter plusieurs sources de données >

Processus de découverte et d'analyse


  • Résumé

  • Contexte

    Récemment en utilisant le druide Alibaba, j'ai découvert accidentellement un petit bug lors de la connexion de plusieurs sources de données. J'ai soumis un problème avec github et il a été officiellement corrigé. adresse du problème :
  • Processus de découverte et d'analyse

    Le framework de développement Java que nous utilisons est encapsulé. La prise en charge des sources de données par le framework est basée sur l'architecture maître et esclave, c'est-à-dire qu'il peut s'agir d'un ensemble de plusieurs sources de données esclaves, et l'écriture maître-esclave et la commutation de requêtes seront automatiquement effectuées en interne.
Nous sommes maintenant en train de convertir .net en Java. Dans des scénarios spéciaux, le nouveau système Java doit se connecter à deux sources de données. La source de données mysql est connectée par défaut, mais il est parfois nécessaire de le faire. interrogez la source de données sqlserver pour obtenir des données de compatibilité.

Ainsi, lors de la configuration de la deuxième source de données, la charge du système signale une erreur.

Nous utilisons le framework Springboot et la configuration de la source de données est configurée en fonction des propriétés Springboot. Utilisez ensuite la configuration pour créer des beans druid daasource automatiques. Cela ne semble pas poser de problème.

S'il ne s'agit pas de Springboot, vous initialiserez généralement vous-même toutes les propriétés. Chargez la configuration à partir du fichier de configuration et définissez le bean DruidDataSource manuellement.

Je n’ai pas beaucoup réfléchi et je l’ai simplement utilisé de cette façon. Mais au démarrage, une erreur était signalée lors de l’initialisation du bean.


'maxEvictableIdleTimeMillis' a lancé une exception ; l'exception imbriquée est java.lang.IllegalArgumentException : maxEvictableIdleTimeMillis doit être supérieur à minEvictableIdleTimeMillis

    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "ecommon.order.druid")
    public DataSource getOrderDataSource() {
       return new DruidDataSource();
    }
Cela signifie probablement que le temps de survie maximum de 'maxEvictableIdleTimeMillis' doit être supérieure à la durée de vie minimale de « minEvictableIdleTimeMillis ».

La première réaction doit être que la configuration est fausse, vérifiez la configuration.

Cela semble être correct, puis sous le débogage, le même problème se produit. L'ordre des attributs minEvictableIdleTimeMillis et maxEvictableIdleTimeMillis semble correct. Après l'avoir essayé, j'ai inversé l'ordre des deux attributs, mais le problème persistait.

État aveugle~_~.

Je pense que ce problème est un peu étrange. Le temps presse, donc je trouve directement l'endroit où l'erreur est signalée et je trace le code source.

Accédez à la page d'accueil de github search alibaba druid, clonez-la directement et localisez l'emplacement de l'invite d'erreur.

Il existe deux endroits où cette exception est levée lors de la recherche globale.
##一个连接在池中最小生存的时间(ms)
ecommon.order.druid.minEvictableIdleTimeMillis=300000
##一个连接在池中最大生存的时间(ms)
ecommon.order.druid.maxEvictableIdleTimeMillis=600000
1 : méthode init

Pour faciliter la lecture, j'ai supprimé le code dans init qui nous est inutile pour analyser le problème.

Deux : méthode setMaxEvictableIdleTimeMillis

La logique de ces deux méthodes est relativement simple. Les valeurs de ces deux attributs du bean seront vérifiées lors de l'initialisation de l'initialisation. setMaxEvictableIdleTimeMillis, il y a une vérification lors de la définition de la durée de survie maximale. Si votre temps de survie maximum est inférieur au temps de survie minimum, une erreur sera directement signalée.

Il suffit donc de mettre des points d'arrêt à ces deux endroits, puis de déboguer, et de savoir essentiellement où se situe le problème en traçant les valeurs des variables.
public void init() throws SQLException {
            if (maxEvictableIdleTimeMillis < minEvictableIdleTimeMillis) {
                throw new SQLException("maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis");
            }

Grâce au débogage, j'ai découvert que l'utilisation directe de la source de données avec new DruidDataSource() n'irait pas vers la méthode init. Vous n'entrerez pas dans l'endroit où l'erreur est déclenchée. Il semble que mon chemin de code ne devrait pas générer cette vérification. Continuez à exécuter et voyez ce qui se passe avec la méthode setMaxEvictableIdleTimeMillis.

Problème détecté lors de l'exécution de la méthode setMaxEvictableIdleTimeMillis, la valeur de l'attribut minEvictableIdleTimeMillis est 1800000.

    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;
    }
Regardez d'où vient cette valeur.

La propriété minEvictableIdleTimeMillis a une valeur par défaut. L'unité est ms (milliseconde), donc la valeur par défaut ici est de 30 m (minutes) minutes.

Nous avons configuré 600 000 ms, il est donc inférieur à 1 800 000. Mais c'est étrange, nous définissons clairement le paramètre minEvictableIdleTimeMillis. Pourquoi ça n'a pas marché ? J'ai tout de suite pensé que c'était un problème de séquence.

Ensuite, continuez le débogage, contournez d'abord cette vérification pour voir si la méthode setMinEvictableIdleTimeMillis est exécutée après la méthode setMaxEvictableIdleTimeMillis, provoquant un conflit entre cette vérification et l'ordre de configuration.

Après le débogage, c'est bien là le problème. Ensuite, j'étais curieux de savoir comment le framework que nous utilisons maintenant nous aide à encapsuler Druid. En regardant le code source du framework, il contient un tri de hashcode, qui résout ce problème. (Effectivement, un pilote vétéran et un maître) Je n'entrerai pas dans les détails ici.
protected volatile long  minEvictableIdleTimeMillis  = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
public static final long  DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 
1000L * 60L * 30L;
Donc si on résout ce problème, c'est en fait très simple. Il est quand même très simple de savoir par où contourner le problème.

Un : obtenez d'abord les paramètres minEvictableIdleTimeMillis et maxEvictableIdleTimeMillis dans

Deux : définissez ensuite ces deux propriétés vous-même d'abord, et il n'y aura aucune erreur lors de la configuration automatique du Springboot

L’analyse du problème s’arrête ici. Ce petit bug a été corrigé par Alibaba Druid.

Si vous souhaitez savoir comment résoudre ce problème, veuillez consulter le code de Druid sur la correction de la configuration automatique :

Résumé

Tout à coup, vous comprenez que vous avez déjà bénéficié des avantages de l'open source. Vous pouvez participer à son utilisation ensemble, à la découverte de problèmes ensemble et à la correction de bugs ensemble. C’est peut-être la valeur technique fondamentale derrière d’excellentes œuvres d’art telles que Linux et git.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn