Detailed Explanation of GenericObjectPool Configuration Parameters of Object Pool

Detailed Explanation of GenericObjectPool Configuration Parameters of Object Pool

rely

    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
        <version>2.4.3</version>
    </dependency>

To use GenericObjectPool , it is necessary to understand GenericObjectPoolConfig . The configuration parameters will be explained below.

1. Parent class BaseObjectPoolConfig configuration parameters

/**
 * Provides the implementation for the common attributes shared by the
 * sub-classes. New instances of this class will be created using the defaults
 * defined by the public constants.
 * <p>
 * This class is not thread-safe.
 *  * @since 2.0
 */
public abstract class BaseObjectPoolConfig extends BaseObject implements Cloneable {
    private boolean lifo = DEFAULT_LIFO;

    private boolean fairness = DEFAULT_FAIRNESS;

    private long maxWaitMillis = DEFAULT_MAX_WAIT_MILLIS;

    private long minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;

    private long evictorShutdownTimeoutMillis = DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS;

    private long softMinEvictableIdleTimeMillis = DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;

    private int numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN;

    private String evictionPolicyClassName = DEFAULT_EVICTION_POLICY_CLASS_NAME;

    private boolean testOnCreate = DEFAULT_TEST_ON_CREATE;

    private boolean testOnBorrow = DEFAULT_TEST_ON_BORROW;

    private boolean testOnReturn = DEFAULT_TEST_ON_RETURN;

    private boolean testWhileIdle = DEFAULT_TEST_WHILE_IDLE;

    private long timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;

    private boolean blockWhenExhausted = DEFAULT_BLOCK_WHEN_EXHAUSTED;

    private boolean jmxEnabled = DEFAULT_JMX_ENABLE;

    private String jmxNamePrefix = DEFAULT_JMX_NAME_PREFIX;

    private String jmxNameBase = DEFAULT_JMX_NAME_BASE;
}
  • lifo
    provides pools with two behavior modes: last in, first out (LIFO) and first in first out (FIFO); the
    default DEFAULT_LIFO = true, when there are free objects available in the pool, calling the borrowObject method will return the most recent (last in) instance.
    org.apache.commons.pool2.impl.GenericObjectPool

        if (getLifo()) {
            idleObjects.addFirst(p);
        } else {
            idleObjects.addLast(p);
        }
  • fairness
    Whether to use when acquiring resources from the pool or returning resources to the pool; the fairness lock mechanism of java.util.concurrent.locks.ReentrantLock.ReentrantLock.
    Default DEFAULT_FAIRNESS = false
    org.apache.commons.pool2.impl.GenericObjectPool

    idleObjects = new LinkedBlockingDeque<PooledObject<T>>(config.getFairness());
  • maxWaitMillis
    When the connection pool resources are exhausted, the maximum waiting time (unit: milliseconds) for the caller to obtain a connection; the
    default value is DEFAULT_MAX_WAIT_MILLIS = -1L, which will never time out.
    org.apache.commons.pool2.impl.GenericObjectPool

    @Override
    public T borrowObject() throws Exception {
        return borrowObject(getMaxWaitMillis());
    }
  • minEvictableIdleTimeMillis
    connection minimum idle time, after reaching this value, the idle connection may be removed (also depends on whether the maximum number of idle connections has been reached); the
    default value DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L 60L 30L
    org.apache.commons.pool2.impl.GenericObjectPool

    final EvictionConfig evictionConfig = new EvictionConfig(
                        getMinEvictableIdleTimeMillis(),
                        getSoftMinEvictableIdleTimeMillis(),
                        getMinIdle());
  • evictorShutdownTimeoutMillis
    closes the timeout time of the eviction thread; the
    default value DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS = 10L * 1000L
    org.apache.commons.pool2.impl.BaseGenericObjectPool

    final void startEvictor(final long delay) {
        synchronized (evictionLock) {
            if (null != evictor) {
                EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS);
                evictor = null;
                evictionIterator = null;
            }
            if (delay > 0) {
                evictor = new Evictor();
                EvictionTimer.schedule(evictor, delay, delay);
            }
        }
    }
  • softMinEvictableIdleTimeMillis
    is the minimum time that the connection is idle. After reaching this value, the idle link will be removed, and minIdle idle connections will be retained; the
    default value is DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1

  • numTestsPerEvictionRun
    detects the number of idle objects detected each time the idle object thread runs;
    if numTestsPerEvictionRun>=0, then the smaller value of numTestsPerEvictionRun and the number of connections in the pool is used as the number of connections detected each time;
    if numTestsPerEvictionRun<0, each time The number of connections checked is the result of dividing the total number of connections in the pool by the absolute value of this value and rounding up; the
    default value DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3
    org.apache.commons.pool2.impl.GenericObjectPool

        private int getNumTests() {
            final int numTestsPerEvictionRun = getNumTestsPerEvictionRun();
            if (numTestsPerEvictionRun >= 0) {
                return Math.min(numTestsPerEvictionRun, idleObjects.size());
            }
            return (int) (Math.ceil(idleObjects.size() /
                    Math.abs((double) numTestsPerEvictionRun)));
        }
  • evictionPolicyClassName
    The class name of the eviction policy; the
    default value DEFAULT_EVICTION_POLICY_CLASS_NAME = "org.apache.commons.pool2.impl.DefaultEvictionPolicy"
    org.apache.commons.pool2.impl.GenericObjectPool

       public final void setEvictionPolicyClassName(final String evictionPolicyClassName) {
            try {
                Class<?> clazz;
                try {
                    clazz = Class.forName(evictionPolicyClassName, true, Thread.currentThread().getContextClassLoader());
                } catch (final ClassNotFoundException e) {
                    clazz = Class.forName(evictionPolicyClassName);
                }
                final Object policy = clazz.newInstance();
                if (policy instanceof EvictionPolicy<?>) {
                    @SuppressWarnings("unchecked") // safe, because we just checked the class
                    final EvictionPolicy<T> evicPolicy = (EvictionPolicy<T>) policy;
                    this.evictionPolicy = evicPolicy;
                } else {
                    throw new IllegalArgumentException("[" + evictionPolicyClassName + "] does not implement EvictionPolicy");
                }
            } catch (final ClassNotFoundException e) {
                throw new IllegalArgumentException("Unable to create EvictionPolicy instance of type " + evictionPolicyClassName, e);
            } catch (final InstantiationException e) {
                throw new IllegalArgumentException("Unable to create EvictionPolicy instance of type " + evictionPolicyClassName, e);
            } catch (final IllegalAccessException e) {
                throw new IllegalArgumentException("Unable to create EvictionPolicy instance of type " + evictionPolicyClassName, e);
            }
        }
  • testOnCreate
    detects whether the object is valid when it is created (true: yes). Configuring true will reduce performance; the
    default value DEFAULT_TEST_ON_CREATE = false.
    org.apache.commons.pool2.impl.GenericObjectPool##borrowObject(final long borrowMaxWaitMillis)

        PooledObject<T> p = null;
        // ...省略
        // 配置true,新创建对象都会检测对象是否有效 【 create && getTestOnCreate() 】
        if (p != null && (getTestOnBorrow() || create && getTestOnCreate())) {
            boolean validate = false;
            Throwable validationThrowable = null;
            try {
                validate = factory.validateObject(p);
            } catch (final Throwable t) {
                PoolUtils.checkRethrow(t);
                validationThrowable = t;
            }
            if (!validate) {
                try {
                    destroy(p);
                    destroyedByBorrowValidationCount.incrementAndGet();
                } catch (final Exception e) {
                    // Ignore - validation failure is more important
                }
                p = null;
                if (create) {
                    final NoSuchElementException nsee = new NoSuchElementException("Unable to validate object");
                    nsee.initCause(validationThrowable);
                    throw nsee;
                }
            }
        }
  • testOnBorrow
    detects whether the object is valid when obtaining the object from the object pool (true: yes), configuring true will reduce performance; the
    default value DEFAULT_TEST_ON_BORROW = false
    org.apache.commons.pool2.impl.GenericObjectPool##borrowObject(final long borrowMaxWaitMillis)**
    // 配置true,从对象池获取对象,总是要检测对象是否有效 【 getTestOnBorrow() 】
    if (p != null && (getTestOnBorrow() || create && getTestOnCreate())) {
        // ...省略
    }
  • testOnReturn
    detects whether the object is valid when returning the object to the object pool (true: yes), the configuration of true will reduce performance; the
    default value DEFAULT_TEST_ON_RETURN = false
    org.apache.commons.pool2.impl.GenericObjectPool##returnObject(final T obj)

        if (getTestOnReturn()) {
            if (!factory.validateObject(p)) {
                try {
                    destroy(p);
                } catch (final Exception e) {
                    swallowException(e);
                }
                try {
                    ensureIdle(1, false);
                } catch (final Exception e) {
                    swallowException(e);
                }
                updateStatsReturn(activeTime);
                return;
            }
        }
  • Whether testWhileIdle
    detects the validity of the object when the thread of detecting idle objects detects that the object does not need to be removed. It is recommended to configure to true, which will not affect performance and ensure safety; the
    default value DEFAULT_TEST_WHILE_IDLE = false
    org.apache.commons.pool2.impl.GenericObjectPool##evict()

        final boolean testWhileIdle = getTestWhileIdle();
        // .... 代码省略
        // 配置为true, 检测空闲对象线程检测到对象不需要移除时,检测对象的有效性
        if (testWhileIdle) {
            boolean active = false;
            try {
                factory.activateObject(underTest);
                active = true;
            } catch (final Exception e) {
                destroy(underTest);
                destroyedByEvictorCount.incrementAndGet();
            }
            if (active) {
                if (!factory.validateObject(underTest)) {
                    destroy(underTest);
                    destroyedByEvictorCount.incrementAndGet();
                } else {
                    try {
                        factory.passivateObject(underTest);
                    } catch (final Exception e) {
                        destroy(underTest);
                        destroyedByEvictorCount.incrementAndGet();
                    }
                }
            }
        }
  • timeBetweenEvictionRunsMillis
    idle connection detection cycle (in milliseconds); if it is a negative value, it means that the detection thread is not run; the
    default value is DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L
    org.apache.commons.pool2.impl.GenericObjectPool

        public GenericObjectPool(final PooledObjectFactory<T> factory, final GenericObjectPoolConfig config) {
            super(config, ONAME_BASE, config.getJmxNamePrefix());
            if (factory == null) {
                jmxUnregister(); // tidy up
                throw new IllegalArgumentException("factory may not be null");
            }
            this.factory = factory;
    
            idleObjects = new LinkedBlockingDeque<PooledObject<T>>(config.getFairness());
    
            setConfig(config);
            // 启动空闲连接检测线程
            startEvictor(getTimeBetweenEvictionRunsMillis());
        }
  • blockWhenExhausted
    When there are no free objects in the object pool, whether the new object acquisition request is blocked (true blocking, maxWaitMillis takes effect; false connection pool without resources immediately throws an exception)
    Default value DEFAULT_BLOCK_WHEN_EXHAUSTED = true
    org.apache.commons.pool2.impl.GenericObjectPool ##borrowObject(final long borrowMaxWaitMillis)

        final boolean blockWhenExhausted = getBlockWhenExhausted();
        // ... 省略
        if (blockWhenExhausted) {
            if (p == null) {
                if (borrowMaxWaitMillis < 0) {
                    p = idleObjects.takeFirst();
                } else {
                    p = idleObjects.pollFirst(borrowMaxWaitMillis,
                            TimeUnit.MILLISECONDS);
                }
            }
            if (p == null) {
                throw new NoSuchElementException(
                        "Timeout waiting for idle object");
            }
        } 
  • Whether jmxEnabled
    is registered with JMX
    default DEFAULT_JMX_ENABLE = true
    org.apache.commons.pool2.impl.BaseGenericObjectPool

        public BaseGenericObjectPool(final BaseObjectPoolConfig config, final String jmxNameBase, final String jmxNamePrefix) {
            if (config.getJmxEnabled()) {
                this.oname = jmxRegister(config, jmxNameBase, jmxNamePrefix);
            } else {
                this.oname = null;
            }
    
            // Populate the creation stack trace
            this.creationStackTrace = getStackTrace(new Exception());
    
            // save the current TCCL (if any) to be used later by the evictor Thread
            final ClassLoader cl = Thread.currentThread().getContextClassLoader();
            if (cl == null) {
                factoryClassLoader = null;
            } else {
                factoryClassLoader = new WeakReference<ClassLoader>(cl);
            }
    
            fairness = config.getFairness();
        }
  • jmxNamePrefix
    JMX prefix
    default value DEFAULT_JMX_NAME_PREFIX = "pool"
    org.apache.commons.pool2.impl.GenericObjectPool

        // JMX specific attributes
        private static final String ONAME_BASE = "org.apache.commons.pool2:type=GenericObjectPool,name=";
    
        public GenericObjectPool(final PooledObjectFactory<T> factory, final GenericObjectPoolConfig config) {
            // 参见上述 jmxEnabled 部分
            super(config, ONAME_BASE, config.getJmxNamePrefix());
            // .....
        }
  • jmxNameBase
    uses base + jmxNamePrefix + i to generate the ObjectName
    default value DEFAULT_JMX_NAME_BASE = null, and the GenericObjectPool construction method uses ONAME_BASE initialization.

        private ObjectName jmxRegister(final BaseObjectPoolConfig config,final String jmxNameBase, String jmxNamePrefix) {
            ObjectName objectName = null;
            final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
            int i = 1;
            boolean registered = false;
            String base = config.getJmxNameBase();
            if (base == null) {
                base = jmxNameBase;
            }
            while (!registered) {
                try {
                    ObjectName objName;
                    if (i == 1) {
                        objName = new ObjectName(base + jmxNamePrefix);
                    } else {
                        objName = new ObjectName(base + jmxNamePrefix + i);
                    }
                    mbs.registerMBean(this, objName);
                    objectName = objName;
                    registered = true;
                } catch (final MalformedObjectNameException e) {
                    if (BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX.equals(jmxNamePrefix) && jmxNameBase.equals(base)) {
                        // 如果走到这步,就跳过jmx注册,应该不会发生
                        registered = true;
                    } else {
                        // 前者使用的名称不是默认配置,则使用默认配置替代
                        jmxNamePrefix =
                                BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX;
                        base = jmxNameBase;
                    }
                } catch (final InstanceAlreadyExistsException e) {
                    // 增加一个索引,再试一次
                    i++;
                } catch (final MBeanRegistrationException e) {
                    // 如果走到这步,就跳过jmx注册,应该不会发生
                    registered = true;
                } catch (final NotCompliantMBeanException e) {
                    // 如果走到这步,就跳过jmx注册,应该不会发生
                    registered = true;
                }
            }
            return objectName;
        }
    

2. Subclass GenericObjectPoolConfig configuration parameters

/**
 * A simple "struct" encapsulating the configuration for a
 * {@link GenericObjectPool}.
 *  * <p>
 * This class is not thread-safe; it is only intended to be used to provide
 * attributes used when creating a pool.
 *  * @since 2.0
 */
public class GenericObjectPoolConfig extends BaseObjectPoolConfig {

    private int maxTotal = DEFAULT_MAX_TOTAL;

    private int maxIdle = DEFAULT_MAX_IDLE;

    private int minIdle = DEFAULT_MIN_IDLE;
}
  • maxTotal
    maximum number of connections, the default value DEFAULT_MAX_TOTAL = 8
  • maxIdle
    maximum number of idle connections, the default value DEFAULT_MAX_IDLE = 8
  • minIdle
    minimum number of idle connections, the default value DEFAULT_MIN_IDLE = 0

Guess you like

Origin blog.51cto.com/huazie/2676978