Casbin 导致的数据库连接满
现状
开发环境运行,每次页面刷新都会请求后端服务查询用户信息(没有加缓存,每次查询数据库),突然开始数据库报错
too Many Connections 排查
数据库连接池满,首先去查看数据库的连接池配置和项目中数据库连接池的配置。
数据库信息
数据库连接池
show variables like '%max_connections%';
max_connections 128如果要设置数据库连接的最大值呢?
// 设置最大连接数 1000,但是如果数据库重启,就会失效,要永久有效需要配置到 MySQL 的配置文件
set GLOBAL max_connections=1000; 查看连接进程
show processlist;
2313 root localhost:50629 Sleep 53111
2313 root localhost:60621 Sleep 33149
2313 root localhost:50893 Sleep 22447
...
2313 root localhost:50609 Sleep 13143
2314 root localhost:50610 casbin Sleep 13143
...
2315 root localhost:56672 gdcloud Query 0 starting show processlist可以看到连接有一大波的进程是处于 Sleep 状态,MySQL 被建立了很多连接但是没有使用
项目 Gorm 数据库配置
最大打开连接数 100
最大闲置连接数 10
连接最大保持时间 1小时
但是 MySQL 的 process 是大于 100的,并且观察请求日志因为涉及到权限,每次请求都会走 casbin 的代码访问,因为项目中除了 gorm 外就 casbin 和数据库有交互。
Casbin 持久化逻辑
代码从其它列子抄来的,未曾琢磨
看了下代码,就猜到是 Casbin 的问题了,因为每次页面请求都会验证角色权限,而每次都会调用 casbin.Casbin(),它又是调用到了 gormadapter.NewAdapter() ,每一次都会 New 的话就很可能占用了一次连接。继续跟进去:
可以看到这里有 a.open() 操作,写着打开一个 DB,点进去看:
看到这里的 openDBConnection() 就彻底明白了,*gorm.DB 对象每一次都会创建,每一次创建都会建立连接,最终导致 MySQL 连接满。
改进
每次连接改成创建的对象的时候创建一次连接,后面共用 *gorm.DB。
因为暂时配置目前不需要动态刷新,所以直接共享了下面两个变量:
后面对 casbin 的操作都基于了 enforcer。
最后更新于
这有帮助吗?