## 前言 群里老有同学问,`go-zero` 的 `数据库` 和 `redis` 库是否有连接池支持。先说结论:**有的,可以放心大胆用!** 从框架设计来说,对于数据库连接这种资源当然是尽可能减少频繁操作: 1. 为业务减负 2. 提升框架自身的性能 3. 池化技术是一个通用化技术,本身就应该作为一个通用库支撑框架的上层业务 所以不管是 `sqlx`,`redis`,以及 `mongo`,等以后可能要支持的数据源类型,底层的池化处理都是通用的;所以当开发者需要一个池化处理组件时,`go-zero` 也是提供的。 池化技术支持的库就位于:`core/resourcemanager.go`。下面来看看这个库的使用~~ ## 使用 使用的话,我们直接来看 `sqlx` ,它是怎么用的: ```go // 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 } ``` 说说其中的要点: 1. `NewResourceManager`:创建一个池子 2. `GetResource(key, createFunc)`:key是用来防止并发获取资源时重复请求,`createFunc` 才是正在用来创建资源的函数【此函数需要有开发者自己编写符合业务需求资源】 总结一下资源池的模型: ```go // 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; } ``` ## 整体分析 ![](https://oscimg.oschina.net/oscnet/up-eb2da6a3ff37a29eddc0af5f4b841ec51de.png) 其实流程上很简单,其中还有我们老生常谈的 `sharedCalls`: 1. `GetResource`,携带特定的 `key`,到资源池中的 `map` 中查找: - 查到了,直接返回 - 没有查到,调用传入的 `create()` ;此处才真正创建一个真实的资源连接,并放入 `map` 2. 其中对 `map` 的查询和写入,都得加锁。 3. 其中在对资源池进行操作时,附加上 `sharedCalls` :防止并发请求时无效流量请求以及共享请求结果。 > 关于 `SharedCalls`,还不清楚的同学,可以到 `go-zero` 官方文档中仔细查看。 ## 总结 本篇文章对 `go-zero` 的资源池库从使用到结构进行了分析。大家也可以在业务中常发生资源申请的逻辑处,加上 `resourcemanager`,本质上也是给资源加上一个缓存,节省反复创建。 关于 `go-zero` 更多的设计和实现文章,可以关注『微服务实践』公众号。 ## 项目地址 [https://github.com/tal-tech/go-zero](https://github.com/tal-tech/go-zero) 欢迎使用 go-zero 并 **star** 支持我们! ## 微信交流群 关注『**微服务实践**』公众号并点击 **交流群** 获取社区群二维码。