database/sql包连接池解读

连接池是做网络应用经常用到的一个概念,可以缓存连接减少创建连接的损耗。那么在golang中应该如何做一个连接池,在这里会通过解读database/sql包的连接池实现来给自己一些参考和启发。
首先,需要了解database/sql的基本原理和使用方法,请参考下面的链接仔细阅读:http://go-database-sql.org/overview.html
接下来分析下建立新连接的基本流程:

database/sql包连接池解读_第1张图片
database/sql连接池分析-1.jpg

然后是释放连接的基本流程:

database/sql包连接池解读_第2张图片
database/sql连接池分析-2.jpg

最后,有几个关键函数也想说明一下:
在调用sql.Open的时候,会创建一个协程“go db.connectionOpener()“

// Runs in a separate goroutine, opens new connections when requested.
func (db *DB) connectionOpener() {
    for range db.openerCh {
        db.openNewConnection()
    }
}

那这个函数是做什么用的呢?我们发现有db.openerCh,用到这个channel的函数只有db.maybeOpenNewConnections()函数

func (db *DB) maybeOpenNewConnections() {
    numRequests := len(db.connRequests)
    if db.maxOpen > 0 {
        numCanOpen := db.maxOpen - db.numOpen
        if numRequests > numCanOpen {
            numRequests = numCanOpen
        }
    }
    for numRequests > 0 {
        db.numOpen++ // optimistically
        numRequests--
        if db.closed {
            return
        }
        db.openerCh <- struct{}{}
    }
}

maybeOpenNewConnections只有在创建连接失败或者释放连接失败或者发生error的时候才会调用,这样就能够保证不会有阻塞的获取连接的请求得不到资源。例如释放连接时,发生了错误,此时有阻塞的获取连接请求,如果直接返回,那么等待池会继续阻塞。此时就可以调用maybeOpenNewConnections函数建立新的连接。

你可能感兴趣的:(database/sql包连接池解读)