前言
群里老有同学问, go-zero 的 数据库 和 Redis 库是否有连接池支持. 先说结论: 有的, 可以放心大胆用!
从框架设计来说, 对于数据库连接这种资源当然是尽可能减少频繁操作:
为业务减负
提升框架自身的性能
池化技术是一个通用化技术, 本身就应该作为一个通用库支撑框架的上层业务
所以不管是 sqlx,Redis, 以及 mongo, 等以后可能要支持的数据源类型, 底层的池化处理都是通用的; 所以当开发者需要一个池化处理组件时, go-zero 也是提供的.
池化技术支持的库就位于: core/resourcemanager.go. 下面来看看这个库的使用~~
使用
使用的话, 我们直接来看 sqlx , 它是怎么用的:
- // 1. 初始化
- var connManager = syncx.NewResourceManager()
- func getCachedSqlConn(driverName, server string) (*db, error) {
- val, err := connManager.GetResource(server, func() (io.Closer, error) {
- // 2. 此处才是真正创建连接的地方
- conn, err := newDBConnection(driverName, server)
- ...
- // 3. 将连接返回给连接池 [内部也肯定是存起来]
- return &db{
- DB: conn,
- }, nil
- })
- ...
- return val.(*db), nil
- }
说说其中的要点:
NewResourceManager: 创建一个池子
GetResource(key, createFunc)
:key 是用来防止并发获取资源时重复请求, createFunc 才是正在用来创建资源的函数 [此函数需要有开发者自己编写符合业务需求资源]
总结一下资源池的模型:
- // 1. new
- var manager = NewResourceManager()
- // 2. 业务资源获取函数
- func getResource(key string) (*resource, error) {
- return manager.GetResource(key, createFunc);
- }
- // 3. 业务资源创建函数 [由开发者自己编写, 此处只是一个样例]
- func createFunc() (io.Closer, error) {
- // 打开一个资源
- conn, err := openResource();
- // 设置一下资源配置
- conn.setConfig()
- return conn, err;
- }
整体分析
其实流程上很简单, 其中还有我们老生常谈的 sharedCalls:
GetResource, 携带特定的 key, 到资源池中的 map 中查找:
查到了, 直接返回
没有查到, 调用传入的 create() ; 此处才真正创建一个真实的资源连接, 并放入 map
其中对 map 的查询和写入, 都得加锁.
其中在对资源池进行操作时, 附加上 sharedCalls : 防止并发请求时无效流量请求以及共享请求结果.
关于 SharedCalls, 还不清楚的同学, 可以到 go-zero 官方文档中仔细查看.
总结
本篇文章对 go-zero 的资源池库从使用到结构进行了分析. 大家也可以在业务中常发生资源申请的逻辑处, 加上 resourcemanager, 本质上也是给资源加上一个缓存, 节省反复创建.
关于 go-zero 更多的设计和实现文章, 可以关注『微服务实践』公众号.
项目地址
https://github.com/tal-tech/go-zero
欢迎使用 go-zero 并 star 支持我们!
微信交流群
关注『微服务实践』公众号并点击 交流群 获取社区群二维码.
go-zero 系列文章见『微服务实践』公众号
来源: https://segmentfault.com/a/1190000040064442