• 聊聊druid的return行为


    本文主要研究一下druid的return行为

    close

    com/alibaba/druid/pool/DruidPooledConnection.java

        @Override
        public void close() throws SQLException {
            if (this.disable) {
                return;
            }
    
            DruidConnectionHolder holder = this.holder;
            if (holder == null) {
                if (dupCloseLogEnable) {
                    LOG.error("dup close");
                }
                return;
            }
    
            DruidAbstractDataSource dataSource = holder.getDataSource();
            boolean isSameThread = this.getOwnerThread() == Thread.currentThread();
    
            if (!isSameThread) {
                dataSource.setAsyncCloseConnectionEnable(true);
            }
    
            if (dataSource.isAsyncCloseConnectionEnable()) {
                syncClose();
                return;
            }
    
            if (!CLOSING_UPDATER.compareAndSet(this, 0, 1)) {
                return;
            }
    
            try {
                for (ConnectionEventListener listener : holder.getConnectionEventListeners()) {
                    listener.connectionClosed(new ConnectionEvent(this));
                }
    
                List filters = dataSource.getProxyFilters();
                if (filters.size() > 0) {
                    FilterChainImpl filterChain = new FilterChainImpl(dataSource);
                    filterChain.dataSource_recycle(this);
                } else {
                    recycle();
                }
            } finally {
                CLOSING_UPDATER.set(this, 0);
            }
    
            this.disable = true;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    close方法先从holder获取当前的dataSource,然后判断ownerThread,若不是同一个线程则设置asyncCloseConnectionEnable为true,若asyncCloseConnectionEnable为true则执行syncClose(这里语义貌似相反),否则执行recycle方法

    syncClose

    com/alibaba/druid/pool/DruidPooledConnection.java

        public void syncClose() throws SQLException {
            lock.lock();
            try {
                if (this.disable || CLOSING_UPDATER.get(this) != 0) {
                    return;
                }
    
                DruidConnectionHolder holder = this.holder;
                if (holder == null) {
                    if (dupCloseLogEnable) {
                        LOG.error("dup close");
                    }
                    return;
                }
    
                if (!CLOSING_UPDATER.compareAndSet(this, 0, 1)) {
                    return;
                }
    
                for (ConnectionEventListener listener : holder.getConnectionEventListeners()) {
                    listener.connectionClosed(new ConnectionEvent(this));
                }
    
                DruidAbstractDataSource dataSource = holder.getDataSource();
                List filters = dataSource.getProxyFilters();
                if (filters.size() > 0) {
                    FilterChainImpl filterChain = new FilterChainImpl(dataSource);
                    filterChain.dataSource_recycle(this);
                } else {
                    recycle();
                }
    
                this.disable = true;
            } finally {
                CLOSING_UPDATER.set(this, 0);
                lock.unlock();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    syncClose方法主要是加锁执行recycle

    recycle

        public void recycle() throws SQLException {
            if (this.disable) {
                return;
            }
    
            DruidConnectionHolder holder = this.holder;
            if (holder == null) {
                if (dupCloseLogEnable) {
                    LOG.error("dup close");
                }
                return;
            }
    
            if (!this.abandoned) {
                DruidAbstractDataSource dataSource = holder.getDataSource();
                dataSource.recycle(this);
            }
    
            this.holder = null;
            conn = null;
            transactionInfo = null;
            closed = true;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    recycle方法主要是执行dataSource.recycle(this)

    DruidDataSource.recycle

    com/alibaba/druid/pool/DruidDataSource.java

        protected void recycle(DruidPooledConnection pooledConnection) throws SQLException {
            final DruidConnectionHolder holder = pooledConnection.holder;
    
            if (holder == null) {
                LOG.warn("connectionHolder is null");
                return;
            }
    
            if (logDifferentThread //
                    && (!isAsyncCloseConnectionEnable()) //
                    && pooledConnection.ownerThread != Thread.currentThread()//
            ) {
                LOG.warn("get/close not same thread");
            }
    
            final Connection physicalConnection = holder.conn;
    
            if (pooledConnection.traceEnable) {
                Object oldInfo = null;
                activeConnectionLock.lock();
                try {
                    if (pooledConnection.traceEnable) {
                        oldInfo = activeConnections.remove(pooledConnection);
                        pooledConnection.traceEnable = false;
                    }
                } finally {
                    activeConnectionLock.unlock();
                }
                if (oldInfo == null) {
                    if (LOG.isWarnEnabled()) {
                        LOG.warn("remove abandonded failed. activeConnections.size " + activeConnections.size());
                    }
                }
            }
    
            final boolean isAutoCommit = holder.underlyingAutoCommit;
            final boolean isReadOnly = holder.underlyingReadOnly;
            final boolean testOnReturn = this.testOnReturn;
    
            try {
                // check need to rollback?
                if ((!isAutoCommit) && (!isReadOnly)) {
                    pooledConnection.rollback();
                }
    
                // reset holder, restore default settings, clear warnings
                boolean isSameThread = pooledConnection.ownerThread == Thread.currentThread();
                if (!isSameThread) {
                    final ReentrantLock lock = pooledConnection.lock;
                    lock.lock();
                    try {
                        holder.reset();
                    } finally {
                        lock.unlock();
                    }
                } else {
                    holder.reset();
                }
    
                if (holder.discard) {
                    return;
                }
    
                if (phyMaxUseCount > 0 && holder.useCount >= phyMaxUseCount) {
                    discardConnection(holder);
                    return;
                }
    
                if (physicalConnection.isClosed()) {
                    lock.lock();
                    try {
                        if (holder.active) {
                            activeCount--;
                            holder.active = false;
                        }
                        closeCount++;
                    } finally {
                        lock.unlock();
                    }
                    return;
                }
    
                if (testOnReturn) {
                    boolean validate = testConnectionInternal(holder, physicalConnection);
                    if (!validate) {
                        JdbcUtils.close(physicalConnection);
    
                        destroyCountUpdater.incrementAndGet(this);
    
                        lock.lock();
                        try {
                            if (holder.active) {
                                activeCount--;
                                holder.active = false;
                            }
                            closeCount++;
                        } finally {
                            lock.unlock();
                        }
                        return;
                    }
                }
                if (holder.initSchema != null) {
                    holder.conn.setSchema(holder.initSchema);
                    holder.initSchema = null;
                }
    
                if (!enable) {
                    discardConnection(holder);
                    return;
                }
    
                boolean result;
                final long currentTimeMillis = System.currentTimeMillis();
    
                if (phyTimeoutMillis > 0) {
                    long phyConnectTimeMillis = currentTimeMillis - holder.connectTimeMillis;
                    if (phyConnectTimeMillis > phyTimeoutMillis) {
                        discardConnection(holder);
                        return;
                    }
                }
    
                lock.lock();
                try {
                    if (holder.active) {
                        activeCount--;
                        holder.active = false;
                    }
                    closeCount++;
    
                    result = putLast(holder, currentTimeMillis);
                    recycleCount++;
                } finally {
                    lock.unlock();
                }
    
                if (!result) {
                    JdbcUtils.close(holder.conn);
                    LOG.info("connection recyle failed.");
                }
            } catch (Throwable e) {
                holder.clearStatementCache();
    
                if (!holder.discard) {
                    discardConnection(holder);
                    holder.discard = true;
                }
    
                LOG.error("recyle error", e);
                recycleErrorCountUpdater.incrementAndGet(this);
            }
        }
    
        boolean putLast(DruidConnectionHolder e, long lastActiveTimeMillis) {
            if (poolingCount >= maxActive || e.discard || this.closed) {
                return false;
            }
    
            e.lastActiveTimeMillis = lastActiveTimeMillis;
            connections[poolingCount] = e;
            incrementPoolingCount();
    
            if (poolingCount > poolingPeak) {
                poolingPeak = poolingCount;
                poolingPeakTime = lastActiveTimeMillis;
            }
    
            notEmpty.signal();
            notEmptySignalCount++;
    
            return true;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173

    recycle方法先执行DruidConnectionHolder的reset方法,之后针对大于等于phyMaxUseCount的场景执行discardConnection;针对testOnReturn为true,则执行testConnectionInternal校验,校验失败则关闭连接;最后加锁执行putLast把连接放回连接池,若归还失败则关闭连接。

    小结

    close方法先从holder获取当前的dataSource,然后判断ownerThread,若不是同一个线程则设置asyncCloseConnectionEnable为true,若asyncCloseConnectionEnable为true则执行syncClose(这里语义貌似相反),否则执行recycle方法。

  • 相关阅读:
    C++基础01
    vscode更改为中文版本
    Elasticsearch(macbook搭建,Elasticsearch+kibana)一步到位
    jmeter采集ELK平台海量业务日志( 采用Scroll)
    猿创征文|Linux 常用命令大全
    #分库分表-分片算法
    【JavaScript】关键字function的点滴
    二叉树(binary tree)
    logistic挤压型激活函数(机器学习)
    期货开户前先判定期货公司正规性
  • 原文地址:https://blog.csdn.net/hello_ejb3/article/details/133294712