Golang语言社区--golang通用连接池的实现

前端之家收集整理的这篇文章主要介绍了Golang语言社区--golang通用连接池的实现前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
golang的channel除了goroutine通信之外还有很多其他的功能,本文将实现一种基于channel的通用连接池。
何为通用?
连接池的实现不依赖具体的实例,而依赖某个接口,本文的连接池选用的是io.Closer接口,只要是实现了该接口的对象都可以被池管理。
当然,你可以实现基于interface{}的连接池,这样任何对象都可以被管理。
实现原理
将连接句柄存入channel中,由于缓存channel的特性,获取连接时如果池中有连接,将直接返回,如果池中没有连接,将阻塞或者新建连接(没超过最大限制的情况下)。
由于面向接口编程,所有创建连接的逻辑是不清楚的,这里需要传入一个函数,该函数返回一个io.Closer对象。
实现
由于并发问题,在需要操作池中互斥数据的时候需要加锁。
  1. package pool

  2. import (
  3. "errors"
  4. "io"
  5. "sync"
  6. "time"
  7. )
  8. var (
  9. ErrInvalidConfig = errors.New("invalid pool config")
  10. ErrPoolClosed = errors.New("pool closed")
  11. type factory func() (io.Closer,error)
  12. type Pool interface {
  13. Acquire() (io.Closer,error) // 获取资源
  14. Release(io.Closer) error // 释放资源
  15. Close(io.Closer) error // 关闭资源
  16. Shutdown() error // 关闭
  17. }
  18. type GenericPool struct {
  19. sync.Mutex
  20. pool chan io.Closer
  21. maxOpen int// 池中最大资源数
  22. numOpen int// 当前池中资源数
  23. minOpen int// 池中最少资源数
  24. closed bool // 池是否已关闭
  25. maxLifetime time.Duration
  26. factory factory // 创建连接的方法
  27. func NewGenericPool(minOpen,maxOpen int,maxLifetime time.Duration,factory factory) (*GenericPool,error) {
  28. if maxOpen <= 0 || minOpen > maxOpen {
  29. return nil,ErrInvalidConfig
  30. }
  31. p := &GenericPool{
  32. maxOpen: maxOpen,
  33. 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++ {
  34. closer,err := factory()
  35. if err != nil {
  36. continue
  37. p.numOpen++
  38. p.pool <- closer
  39. return p,nil
  40. func (p *GenericPool) Acquire() (io.Closer,serif;font-size:12px;line-height:1.8em;"> if p.closed {
  41. for {
  42. return nil,err
  43. // todo maxLifttime处理
  44. 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 {
  45. case closer := <-p.pool:
  46. default:
  47. p.Lock()
  48. if p.numOpen >= p.maxOpen {
  49. closer := <-p.pool
  50. p.Unlock()
  51. // 新建连接
  52. // 释放单个资源到连接池
  53. func (p *GenericPool) Release(closer io.Closer) error {
  54. return ErrPoolClosed
  55. return nil
  56. // 关闭单个资源
  57. func (p *GenericPool) Close(closer io.Closer) error {
  58. closer.Close()
  59. p.numOpen--
  60. // 关闭连接池,释放所有资源
  61. func (p *GenericPool) Shutdown() error {
  62. close(p.pool)
  63. for closer := range p.pool {
  64. p.closed = true
  65. }
复制代码
结论
基于该连接池,可以管理所有io.Closer对象。比如memcached,redis等等,非常方便!

Golang语言社区论坛网址:www.golang.ltd

猜你在找的Go相关文章