Redigo Connection Pool Code Analysis

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Structural Body Analysis

type Pool struct {    // 用来创建redis连接的方法    Dial func() (Conn, error)    // 如果设置了给func,那么每次p.Get()的时候都会调用改方法来验证连接的可用性    TestOnBorrow func(c Conn, t time.Time) error    // 定义连接池中最大连接数(超过这个数会关闭老的链接,总会保持这个数)    MaxIdle int    // 当前连接池中可用的链接数.    MaxActive int    // 定义链接的超时时间,每次p.Get()的时候会检测这个连接是否超时(超时会关闭,并释放可用连接数).    IdleTimeout time.Duration    // 当可用连接数为0是,那么当wait=true,那么当调用p.Get()时,会阻塞等待,否则,返回nil.    Wait bool    // 读写锁控制.    mu     sync.Mutex    // 用来条件控制,这里主要是当链接被关闭时,提醒在等待的进程可以使用了,或者可以自行创建了    cond   *sync.Cond    // 当前连接池是否已经关闭    closed bool    // 当前可用的链接数    active int    // 链接存储在一个栈中.    idle list.List}

Connection pooling Shutdown method

func (p *Pool) Close() error {    p.mu.Lock()    // 获取连接池所有链接栈    idle := p.idle    // 重新初始化    p.idle.Init()    // 标示已经关闭    p.closed = true    // 控制可用连接数    p.active -= idle.Len()    // 如果当前有进程正在等待获取的话,则通知可以获取或者自行创建    if p.cond != nil {        p.cond.Broadcast()    }    p.mu.Unlock()    // 遍历栈,逐个关闭链接    for e := idle.Front(); e != nil; e = e.Next() {        e.Value.(idleConn).c.Close()    }    return nil}

Release a link

func (p *Pool) release() {    // 当链接超时,或者ping不通,或者创建失败,则立即使用链接表示    p.active -= 1    // 如果已经有进程在之前等待了,则通知其使用或者自行创建    if p.cond != nil {        p.cond.Signal()    }}

Close connection

func (p *Pool) put(c Conn, forceClose bool) error {    err := c.Err()    p.mu.Lock()    // 如果连接池没有关闭,并且不是强制关闭的    if !p.closed && err == nil && !forceClose {        // 把指定的链接放在空闲栈首位        p.idle.PushFront(idleConn{t: nowFunc(), c: c})        // 如果栈的长度大于指定长度,则吧最后一个(可能超时)剔除        if p.idle.Len() > p.MaxIdle {            c = p.idle.Remove(p.idle.Back()).(idleConn).c        } else {            c = nil        }    }    if c == nil {        //成功放回空闲连接通知其他阻塞的进程        if p.cond != nil {            p.cond.Signal()        }        p.mu.Unlock()        return nil    }    // 减少active计数(感觉这里可以不用处理,上面如果是替换的话)    p.release()    p.mu.Unlock()    // 关闭连接    return c.Close()}

Get links

Func (P *pool) get (Conn, error) {P.mu.lock ()//Handle old link (detect if timeout) if timeout: = p.idletimeout; Timeout > 0 { For I, N: = 0, P.idle.len (); I < n; i++ {e: = P.idle.back () if E = = nil {break} IC: = E.value. ( Idleconn)//The time that the link was created plus whether the time-out is less than the current time if Ic.t.add (timeout). After (Nowfunc ()) {break}//Timeout link, remove P.idle.remove (e)//available from stack            The number of connections is reduced and other waiting processes are notified to process P.release () P.mu.unlock ()//Close the current connection ic.c.close ()            P.mu.lock ()}} for {//Gets an available link from the list of connection stacks for I, N: = 0, P.idle.len (); i < n; i++ {             Connect from the front of the idle list, then it must be the connection you just used e: = P.idle.front () if E = = nil {break} Type assertion IC: = E.value.        (idleconn)//Remove P.idle.remove from the stack (e) Test: = P.testonborrow    P.mu.unlock ()//Check link if test = Nil by using Check link function | |            Test (IC.C, ic.t) = = Nil {return ic.c, nil}//Check for problems, close connection ic.c.close ()        P.mu.lock ()//reduces the number of available connections and notifies other processes that processing p.release ()}//detects if the connection pool has been closed. If p.closed {p.mu.unlock () return nil, errors. New ("Redigo:get on Closed Pool")}//If the number of available connections is 0 or less than the maximum available number of available connections, create if p.maxactive = = 0 | | P.active < p.maxactive {dial: = p.dial p.active + 1 P.mu.unlock ()//Connect RE                Dis Server c, err: = dial ()//connection failure closed if err! = Nil {P.mu.lock ()        P.release () P.mu.unlock () c = nil} return c, err}        If no wait is configured, then return nil if!p.wait {p.mu.unlock () return nil, errpoolexhausted} If you configure the wait, thatInitialize, and start waiting until there is a process to notify the link number enough or you can create if P.cond = = Nil {P.cond = sync. Newcond (&AMP;P.MU)} p.cond.wait ()}}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.