├── README.md ├── example └── mgo.go └── pool.go /README.md: -------------------------------------------------------------------------------- 1 | # pool 2 | 通用资源池,动态增加资源实例,并支持空闲资源定时回收功能。 3 | -------------------------------------------------------------------------------- /example/mgo.go: -------------------------------------------------------------------------------- 1 | package mgo 2 | 3 | import ( 4 | "log" 5 | 6 | mgo "gopkg.in/mgo.v2" 7 | 8 | "github.com/henrylee2cn/pool" 9 | ) 10 | 11 | type MgoSrc struct { 12 | *mgo.Session 13 | } 14 | 15 | const ( 16 | CONN_STR = "127.0.0.1:27017" 17 | MAX_CONN = 1024 18 | MAX_IDLE = 512 19 | GC_TIME = 60e9 20 | ) 21 | 22 | var ( 23 | session, err = func() (session *mgo.Session, err error) { 24 | session, err = mgo.Dial(CONN_STR) 25 | if err != nil { 26 | log.Printf("MongoDB:%v\n", err) 27 | } else if err = session.Ping(); err != nil { 28 | log.Printf("MongoDB:%v\n", err) 29 | } else { 30 | session.SetPoolLimit(MAX_CONN) 31 | } 32 | return 33 | }() 34 | 35 | MgoPool = pool.ClassicPool( 36 | MAX_CONN, 37 | MAX_IDLE, 38 | func() (pool.Src, error) { 39 | return &MgoSrc{session.Clone()}, err 40 | }, 41 | GC_TIME) 42 | ) 43 | 44 | // 判断资源是否可用 45 | func (self *MgoSrc) Usable() bool { 46 | if self.Session == nil || self.Session.Ping() != nil { 47 | return false 48 | } 49 | return true 50 | } 51 | 52 | // 使用后的重置方法 53 | func (*MgoSrc) Reset() {} 54 | 55 | // 被资源池删除前的自毁方法 56 | func (self *MgoSrc) Close() { 57 | if self.Session == nil { 58 | return 59 | } 60 | self.Session.Close() 61 | } 62 | 63 | func Refresh() { 64 | session, err = mgo.Dial(CONN_STR) 65 | if err != nil { 66 | log.Printf("MongoDB:%v\n", err) 67 | } else if err = session.Ping(); err != nil { 68 | log.Printf("MongoDB:%v\n", err) 69 | } else { 70 | session.SetPoolLimit(MAX_CONN) 71 | } 72 | } 73 | 74 | func Error() error { 75 | return err 76 | } 77 | -------------------------------------------------------------------------------- /pool.go: -------------------------------------------------------------------------------- 1 | // 通用资源池,动态增加资源实例,并支持空闲资源定时回收功能。 2 | package pool 3 | 4 | import ( 5 | "errors" 6 | "fmt" 7 | "runtime" 8 | "sync" 9 | "time" 10 | ) 11 | 12 | type ( 13 | // 资源池(应设置最大容量) 14 | Pool interface { 15 | // 调用资源池中的资源 16 | Call(func(Src) error) error 17 | // 销毁资源池 18 | Close() 19 | // 返回当前资源数量 20 | Len() int 21 | } 22 | // 经典资源池 23 | classic struct { 24 | srcs chan Src // 资源列表(Src须为指针类型) 25 | capacity int // 资源池容量 26 | maxIdle int // 资源最大空闲数 27 | len int // 当前资源数 28 | factory Factory // 创建资源的方法 29 | gctime time.Duration // 空闲资源回收时间 30 | closed bool // 标记是否已关闭资源池 31 | sync.RWMutex 32 | } 33 | // 资源接口 34 | Src interface { 35 | // 判断资源是否可用 36 | Usable() bool 37 | // 使用后的重置方法 38 | Reset() 39 | // 被资源池删除前的自毁方法 40 | Close() 41 | } 42 | // 创建资源的方法 43 | Factory func() (Src, error) 44 | ) 45 | 46 | const ( 47 | GC_TIME = 60e9 48 | ) 49 | 50 | var ( 51 | closedError = errors.New("资源池已关闭") 52 | ) 53 | 54 | // 构建经典资源池 55 | func ClassicPool(capacity, maxIdle int, factory Factory, gctime ...time.Duration) Pool { 56 | if len(gctime) == 0 { 57 | gctime = append(gctime, GC_TIME) 58 | } 59 | pool := &classic{ 60 | srcs: make(chan Src, capacity), 61 | capacity: capacity, 62 | maxIdle: maxIdle, 63 | factory: factory, 64 | gctime: gctime[0], 65 | closed: false, 66 | } 67 | go pool.gc() 68 | return pool 69 | } 70 | 71 | // 调用资源池中的资源 72 | func (self *classic) Call(callback func(Src) error) (err error) { 73 | var src Src 74 | wait: 75 | self.RLock() 76 | if self.closed { 77 | self.RUnlock() 78 | return closedError 79 | } 80 | select { 81 | case src = <-self.srcs: 82 | self.RUnlock() 83 | if !src.Usable() { 84 | self.del(src) 85 | goto wait 86 | } 87 | default: 88 | self.RUnlock() 89 | err = self.incAuto() 90 | if err != nil { 91 | return err 92 | } 93 | runtime.Gosched() 94 | goto wait 95 | } 96 | defer func() { 97 | if p := recover(); p != nil { 98 | err = fmt.Errorf("%v", p) 99 | } 100 | self.recover(src) 101 | }() 102 | err = callback(src) 103 | return err 104 | } 105 | 106 | // 销毁资源池 107 | func (self *classic) Close() { 108 | self.Lock() 109 | defer self.Unlock() 110 | if self.closed { 111 | return 112 | } 113 | self.closed = true 114 | for i := len(self.srcs); i >= 0; i-- { 115 | (<-self.srcs).Close() 116 | } 117 | close(self.srcs) 118 | self.len = 0 119 | } 120 | 121 | // 返回当前资源数量 122 | func (self *classic) Len() int { 123 | self.RLock() 124 | defer self.RUnlock() 125 | return self.len 126 | } 127 | 128 | // 空闲资源回收协程 129 | func (self *classic) gc() { 130 | for !self.isClosed() { 131 | self.Lock() 132 | extra := len(self.srcs) - self.maxIdle 133 | if extra > 0 { 134 | self.len -= extra 135 | for ; extra > 0; extra-- { 136 | (<-self.srcs).Close() 137 | } 138 | } 139 | self.Unlock() 140 | time.Sleep(self.gctime) 141 | } 142 | } 143 | 144 | func (self *classic) incAuto() error { 145 | self.Lock() 146 | defer self.Unlock() 147 | if self.len >= self.capacity { 148 | return nil 149 | } 150 | src, err := self.factory() 151 | if err != nil { 152 | return err 153 | } 154 | self.srcs <- src 155 | self.len++ 156 | return nil 157 | } 158 | 159 | func (self *classic) del(src Src) { 160 | src.Close() 161 | self.Lock() 162 | self.len-- 163 | self.Unlock() 164 | } 165 | 166 | func (self *classic) recover(src Src) { 167 | self.RLock() 168 | defer self.RUnlock() 169 | if self.closed { 170 | return 171 | } 172 | src.Reset() 173 | self.srcs <- src 174 | } 175 | 176 | func (self *classic) isClosed() bool { 177 | self.RLock() 178 | defer self.RUnlock() 179 | return self.closed 180 | } 181 | --------------------------------------------------------------------------------