前端之家收集整理的这篇文章主要介绍了
Golang语言社区--golang通用连接池的实现,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
golang的channel除了goroutine通信之外还有很多其他的功能,本文将实现一种基于channel的通用连接池。
何为通用?
连接池的实现不依赖具体的实例,而依赖某个接口,本文的连接池选用的是io.Closer接口,只要是实现了该接口的对象都可以被池管理。
当然,你可以实现基于interface{}的连接池,这样任何对象都可以被管理。
实现原理
将连接句柄存入channel中,由于缓存channel的特性,
获取连接时如果池中有连接,将直接返回,如果池中没有连接,将阻塞或者新建连接(没超过最大限制的情况下)。
由于面向接口编程,所有创建连接的逻辑是不清楚的,这里需要传入一个
函数,该
函数返回一个io.Closer对象。
实现
由于并发问题,在需要操作池中互斥数据的时候需要加锁。
- package pool
-
- import (
- "errors"
- "io"
- "sync"
- "time"
- )
- var (
- ErrInvalidConfig = errors.New("invalid pool config")
- ErrPoolClosed = errors.New("pool closed")
- type factory func() (io.Closer,error)
- type Pool interface {
- Acquire() (io.Closer,error) // 获取资源
- Release(io.Closer) error // 释放资源
- Close(io.Closer) error // 关闭资源
- Shutdown() error // 关闭池
- }
- type GenericPool struct {
- sync.Mutex
- pool chan io.Closer
- maxOpen int// 池中最大资源数
- numOpen int// 当前池中资源数
- minOpen int// 池中最少资源数
- closed bool // 池是否已关闭
- maxLifetime time.Duration
- factory factory // 创建连接的方法
- func NewGenericPool(minOpen,maxOpen int,maxLifetime time.Duration,factory factory) (*GenericPool,error) {
- if maxOpen <= 0 || minOpen > maxOpen {
- return nil,ErrInvalidConfig
- }
- p := &GenericPool{
- maxOpen: maxOpen,
- minOpen: minOpen,serif;font-size:12px;line-height:1.8em;"> maxLifetime: maxLifetime,serif;font-size:12px;line-height:1.8em;"> factory: factory,serif;font-size:12px;line-height:1.8em;"> pool: make(chan io.Closer,maxOpen),serif;font-size:12px;line-height:1.8em;"> for i := 0; i < minOpen; i++ {
- closer,err := factory()
- if err != nil {
- continue
- p.numOpen++
- p.pool <- closer
- return p,nil
- func (p *GenericPool) Acquire() (io.Closer,serif;font-size:12px;line-height:1.8em;"> if p.closed {
- for {
- return nil,err
- // todo maxLifttime处理
- return closer,serif;font-size:12px;line-height:1.8em;"> func (p *GenericPool) getOrCreate() (io.Closer,serif;font-size:12px;line-height:1.8em;"> select {
- case closer := <-p.pool:
- default:
- p.Lock()
- if p.numOpen >= p.maxOpen {
- closer := <-p.pool
- p.Unlock()
- // 新建连接
- // 释放单个资源到连接池
- func (p *GenericPool) Release(closer io.Closer) error {
- return ErrPoolClosed
- return nil
- // 关闭单个资源
- func (p *GenericPool) Close(closer io.Closer) error {
- closer.Close()
- p.numOpen--
- // 关闭连接池,释放所有资源
- func (p *GenericPool) Shutdown() error {
- close(p.pool)
- for closer := range p.pool {
- p.closed = true
- }
复制代码
结论
基于该连接池,可以管理所有io.Closer对象。比如memcached,redis等等,非常方便!