excellente analyse de code open-source (deux) HikariPool (a) connaissance

Java Geeks | Auteur /   feuille Kengran
Ceci est un geeks Java de 50 articles originaux

1. Qu'est-ce HikariPool

HikariPool est un outil de gestion du pool de connexions de base de données open source, avec d'excellentes performances connues.

2. Que peut-on tirer de la HikariPool

1.HikariPool utiliser beaucoup de concomitance et des outils de gestion de fil, vous pouvez apprendre de leur utilisation.

2. Il y a beaucoup d'utilisation de l'amélioration des performances, nous pouvons apprendre.

3. utilise certaines fonctionnalités de Java, ce qui rend le look de code plus convivial, simple, par exemple:
la définition de 1) int de

// 以下这个定义是合法的,可用_来表示千分位,方便识别具体值是多少,而不用一个个的数
int i = 10_000;
复制代码

2) pour simplifier la classe définie par le Lambda intérieur, par exemple HikariPool.java le code suivant:

         closeConnectionExecutor.execute(() -> {
            quietlyCloseConnection(connection, closureReason);
            if (poolState == POOL_NORMAL) {
               fillPool();
            }
         });
复制代码

Les expressions lambda n'a pas été écrit comme suit:

         closeConnectionExecutor.execute(new Runnable() {
            @Override
            public void run() {
               quietlyCloseConnection(connection, closureReason);
               if (poolState == POOL_NORMAL) {
                  fillPool();
               }
            }
         });
复制代码

Parce que seule une méthode Runnable, donc par

() -> {
复制代码

Vous pouvez également le code suivant, tel code plus concis:

new Runnable() {
            @Override
            public void run() {
            }
复制代码

3, Hatsu 识 HikariPool

la logique de code HikariPool est plus complexe à première vue, commencez ici comment obtenir la connexion de base de données a commencé à le réaliser. L'obtention d'une interface de connexion classes associées comme suit:

3.1, HikariPool

pool de connexion HikariPool classe de gestion, responsable de la gestion de la connexion de base de données.

3.2 ConcurrentBag

ConcurrentBag est un ensemble d'outils de gestion de la concurrence, responsable de la gestion de la mise en commun des ressources, non seulement la connexion de base de données, d'autres ressources mises en commun peuvent être gérées par elle.

3.2.1, la définition de classe

// 通过泛型要求其包含的池化资源必须实现IConcurrentBagEntry接口
public class ConcurrentBag<T extends IConcurrentBagEntry> implements AutoCloseable
复制代码

3.2.2, mise en commun des ressources de l'interface

   // 池化资源接口
   public interface IConcurrentBagEntry
   {
      // 池化资源的状态定义
      int STATE_NOT_IN_USE = 0;
      int STATE_IN_USE = 1;
      int STATE_REMOVED = -1;
      int STATE_RESERVED = -2;

      // 通过CAS操作而非锁来提高并发效率
      boolean compareAndSet(int expectState, int newState);
      void setState(int newState);
      int getState();
   }
复制代码

3.2.3, obtenir PoolEntry

public T borrow(long timeout, final TimeUnit timeUnit) throws InterruptedException
复制代码

Code ConcurrentBag est plus en détail plus loin dans la présentation.

3.3, Piscine d'entrée

PoolEntry est les ressources mises en commun de la classe d'entrée pour obtenir l'interface IConcurrentBagEntry, tout en maintenant une connexion, Connexion pour une gestion facile. Son code qui crée un courtier de connexion est la suivante:

   Connection createProxyConnection(final ProxyLeakTask leakTask, final long now)
   {
      return ProxyFactory.getProxyConnection(this, connection, openStatements, leakTask, now, isReadOnly, isAutoCommit);
   }
复制代码

3.4, ProxyFactory

ProxyFactory utilisée pour obtenir une connexion de base de données.

3.4.1, et tissez des liens

   static ProxyConnection getProxyConnection(final PoolEntry poolEntry, final Connection connection, final FastList<Statement> openStatements, final ProxyLeakTask leakTask, final long now, final boolean isReadOnly, final boolean isAutoCommit)
   {
      // Body is replaced (injected) by JavassistProxyFactory
      throw new IllegalStateException("You need to run the CLI build and you need target/classes in your classpath to run.");
   }
复制代码

1. interne Cette méthode renvoie une exception, la méthode actuelle d'expérience est remplacé JavassistProxyFactory.

2. Ici, plutôt que de retourner ProxyConnection Connection sera plus flexible, facile à mettre en œuvre la surveillance de la base de données. A propos de la base de données de surveillance Référence: la technologie de suivi de la chaîne touche d'appel Java (quatre) Surveillance SQL

3.4.2, JavassistProxyFactory.java

Procédé pour remplacer le type de carrosserie ProxyFactory.

   private static void modifyProxyFactory() throws NotFoundException, CannotCompileException, IOException {
      System.out.println("Generating method bodies for com.zaxxer.hikari.proxy.ProxyFactory");

      String packageName = ProxyConnection.class.getPackage().getName();
      CtClass proxyCt = classPool.getCtClass("com.zaxxer.hikari.pool.ProxyFactory");
      for (CtMethod method : proxyCt.getMethods()) {
         switch (method.getName()) {
           // 这里对getProxyConnection方法体内容做了替换
            case "getProxyConnection":
               method.setBody("{return new " + packageName + ".HikariProxyConnection($$);}");
               break;
            case "getProxyStatement":
               method.setBody("{return new " + packageName + ".HikariProxyStatement($$);}");
               break;
            case "getProxyPreparedStatement":
               method.setBody("{return new " + packageName + ".HikariProxyPreparedStatement($$);}");
               break;
            case "getProxyCallableStatement":
               method.setBody("{return new " + packageName + ".HikariProxyCallableStatement($$);}");
               break;
            case "getProxyResultSet":
               method.setBody("{return new " + packageName + ".HikariProxyResultSet($$);}");
               break;
            case "getProxyDatabaseMetaData":
               method.setBody("{return new " + packageName + ".HikariProxyDatabaseMetaData($$);}");
               break;
            default:
               // unhandled method
               break;
         }
      }
      // 替换后的class直接放到classes目录下    
      proxyCt.writeFile(genDirectory + "target/classes");
   }
复制代码

3.5, ProxyConnection

ProxyConnection est un courtier de connexion, Connexion attente.

3.6, ProxyLeakTask

ProxyLeakTask pour surveiller les connexions de base de données pour les fuites, idées de surveillance:

1. Lorsque vous créez un délai de ScheduledExecutorService de connexion de l'exécution ProxyLeakTask, cette exécution de délai pour la configuration leakDetectionThreshold, si depuis le début pour créer une connexion proxy sur leakDetectionThreshold pas fermer le proxy de connexion, ProxyLeakTask sera exécutée une fois l'exécution est un proxy de connexion peut fuite.

2. Si, dans la connexion leakDetectionThreshold temps Broker est fermé, ProxyLeakTask sera annuler, de sorte qu'il ne sera pas exécuté.

class ProxyLeakTask implements Runnable
{
   private static final Logger LOGGER = LoggerFactory.getLogger(ProxyLeakTask.class);
   static final ProxyLeakTask NO_LEAK;

   // 用于延迟调度ProxyLeakTask
   private ScheduledFuture<?> scheduledFuture;
   private String connectionName;
   private Exception exception;
   private String threadName;
   private boolean isLeaked;

   static
   {
      // 不需要监控连接泄露的ProxyLeakTask的实现类
      NO_LEAK = new ProxyLeakTask() {
         @Override
         void schedule(ScheduledExecutorService executorService, long leakDetectionThreshold) {}

         @Override
         public void run() {}  // 默认啥都不做

         @Override
         public void cancel() {} // 默认啥都不做
      };
   }

   ProxyLeakTask(final PoolEntry poolEntry)
   {
      this.exception = new Exception("Apparent connection leak detected");
      this.threadName = Thread.currentThread().getName();
      this.connectionName = poolEntry.connection.toString();
   }

   private ProxyLeakTask()
   {
   }

   void schedule(ScheduledExecutorService executorService, long leakDetectionThreshold)
   {
      // 通过超过leakDetectionThreshold时间后,延迟调用ProxyLeakTask,来报告泄漏信息
      scheduledFuture = executorService.schedule(this, leakDetectionThreshold, TimeUnit.MILLISECONDS);
   }

   /** {@inheritDoc} */
   @Override
   // 一旦被执行,说明获取连接到关闭超过了leakDetectionThreshold时间
   public void run()
   {
      isLeaked = true;

      final StackTraceElement[] stackTrace = exception.getStackTrace();
      final StackTraceElement[] trace = new StackTraceElement[stackTrace.length - 5];
      System.arraycopy(stackTrace, 5, trace, 0, trace.length);

      exception.setStackTrace(trace);
      // 下面是监控到连接泄漏的处理,这里只是记录到日志中,如果通过一个接口处理,并可以让使用者动态实现会更灵活
      LOGGER.warn("Connection leak detection triggered for {} on thread {}, stack trace follows", connectionName, threadName, exception);
   }

   void cancel()
   {
      scheduledFuture.cancel(false);
      if (isLeaked) {  // 检查到泄漏后连接被关闭,则给一个提示信息
         LOGGER.info("Previously reported leaked connection {} on thread {} was returned to the pool (unleaked)", connectionName, threadName);
      }
   }
}
复制代码

3.7, ProxyLeakTaskFactory

ProxyLeakTaskFactory est une classe d'usine pour créer ProxyLeakTask, raison pour laquelle il y a cette classe d'usine, car il y a différents ProxyLeakTask atteint. Vous pouvez décider si vous souhaitez surveiller la fuite de connexion en fonction de la configuration.

   ProxyLeakTask schedule(final PoolEntry poolEntry)
   {
      // 根据配置来创建不同的代理泄露监控类
      return (leakDetectionThreshold == 0) ? ProxyLeakTask.NO_LEAK : scheduleNewTask(poolEntry);
   }
复制代码

Au-dessus, une compréhension préliminaire de HikariPool, suivie d'une autre plus en détail.

4, adresse de source HiKaripool

1. Code nuage Image
entrepôt 2.github

fin.


Lecture connexe:
la technologie de suivi de la chaîne touche d'appel Java (quatre) SQL Suivi
excellente analyse de code open-source (a) Google goyave de EventBus


Site Java Geek: javageektour.com/

Je suppose que tu aimes

Origine juejin.im/post/5e80b68ce51d45470c12a249
conseillé
Classement