栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

gorm 连接池

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

gorm 连接池

1、背景

前段时间在看gorm,发现gorm是复用database/sql的连接池。

于是翻了下database/sql的数据库连接池的代码实现,看完代码,好像也不是很复杂,但是总觉得理解不够深刻,于是萌生了自己想写个连接池的想法。(最后也验证了,看源码的理解确实不够深刻,一看就会,一做就跪)

2、连接池的实现原理

什么是连接池

  • 顾名思义是一个池子
  • 池子里面存放有限数量即时可用的连接,减少创建连接和关闭连接的时间
  • 连接是有存活时间的

具体到数据库连接池,我根据自己的理解画了一张获取连接的流程图

从上图我们可以看出,除了连接池的容量大小,我们还有一个最大连接数的限制。池子里的连接让我们不用频繁的创建和关闭连接,同时应该也要有最大连接的限制,避免无限制的创建连接导致服务器资源耗尽,拖垮服务不可用。

池子中的连接也有存活时间,如果超过存活时间则会销毁连接。

3、实现连接池我们需要考虑哪些问题

3.1 功能点

  • 获取连接
  • 释放连接
  • Ping
  • 关闭连接池
  • 设置最大连接数和连接池容量(连接存活时间等等)

3.2 实现细节

  • 连接应该有哪些属性,比如最大连接数、连接池容量、连接创建时间和存活时间
  • 如何模拟使用连接池以及超过最大连接数后等待其他连接释放
  • 如何保证在多协程操作下数据的一致性
  • 如果实现连接的超时监听和通知
4、具体实现

这里的连接池实现包括

  • 设置最大连接数和连接池容量
  • 获取连接
  • 释放连接

4.1 结构定义

定义Conn结构体,这里包含了几乎所有的有关连接需要的信息属性

type Conn struct {maxConn int // 最大连接数maxIdle int // 最大可用连接数freeConn int // 线程池空闲连接数connPool []int // 连接池openCount int // 已经打开的连接数waitConn map[int]chan Permission // 排队等待的连接队列waitCount int // 等待个数lock sync.Mutex // 锁nextConnIndex NextConnIndex// 下一个连接的ID标识(用于区分每个ID)freeConns map[int]Permission // 连接池的连接}

这里并不会创建一个真正的数据库连接,而是使用一个非空的Permission表示拿到了连接。拿到一个非空的Permission才有资格执行后面类似增删改查的操作。

Permission对应的结构体如下

type Permission struct {NextConnIndex // 对应Conn中的NextConnIndexContent string // 通行证的具体内容,比如"PASSED"表示成功获取CreatedAt time.Time // 创建时间,即连接的创建时间MaxLifeTime time.Duration // 连接的存活时间,本次没有用到这个属性,保留}

NextConnIndex对应的结构体如下

type NextConnIndex struct {Index int}

还有一个用来设置最大连接数以及连接池最大连接数的Config

type Config struct {MaxConn intMaxIdle int}

4.2 初始化连接池参数

func Prepare(ctx context.Context, config *Config) (conn *Conn) {// go func() {//for {//conn.expiredCh = make(chan string, len(conn.freeConns))//for _, value := range conn.freeConns {//if value.CreatedAt.Add(value.MaxLifeTime).Before(nowFunc()) {//conn.expiredCh 

这里主要是初始化上面的Conn结构体参数。

注释的部分,主要想通过启动一个监听协程,用于监听已经过期的连接,并通过channel发送。(这块还有一些细节没有想清楚,先搁置)

4.3 设置MaxConn和MaxIdle

在main.go中添加代码

ctx := context.Background()config := &custom_pool.Config{MaxConn: 2,MaxIdle: 1,}

这里意味连接池只能缓存一个连接,最大新建连接数为2,超过则要加入等待队列。

4.4 获取连接

// 创建连接func (conn *Conn) New(ctx context.Context) (permission Permission, err error) {conn.lock.Lock()select {default:case  0 {var (popPermission PermissionpopReqKey int)  // 获取其中一个连接for popReqKey, popPermission = range conn.freeConns {break} // 从连接池删除delete(conn.freeConns, popReqKey)fmt.Println("log
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/944554.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号