理解连接池 心已赠人 2021-07-04 22:42 415阅读 0赞 ### 1. 池化技术 ### 池化技术 (Pool) 是一种很常见的编程技巧, 在请求量大时能明显优化应用性能,降低系统频繁建连的资源开销 日常工作中常见的有数据库连接池、线程池、携程池,对象池 它们的特点都是将 “昂贵的”、“费时的” 的资源维护在一个特定的 “池子” 中, 规定其最小连接数、最大连接数、阻塞队列等配置, 方便进行统一管理和复用, 通常还会附带一些探活机制、强制回收、监控一类的配套功能。 ### 2. 数据库连接池 ### 数据库连接池负责分配、管理和释放数据库连接, 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个; 并且释放空闲时间超过最大空闲时间的数据库连接 来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高数据库操作的性能。 ### 2.1 数据库连接池 ### 数据库连接池技术带来的优势: * 资源重用, 减少内存碎片 由于数据库连接得到重用,避免了频繁创建、释放连接引起的大量性能开销。 在减少系统消耗的基础上, 另一方面也增进了系统运行环境的平稳性,减少了内存碎片以及数据库临时进程/线程的数量 * 因为连接已提前准备好, 所以有更快的服务响应速度 数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池中备用。 此时连接的初始化工作均已完成。 对于业务请求处理而言,直接利用现有可用连接, 避免了数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间。 * 新的资源分配手段,强制收回被占用连接, 从而避免某一应用独占所有数据库资源 对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接的配置,实现数据库连接池技术。 通过对应用最大可用数据库连接数的限制,避免某一应用独占所有数据库资源。 统一的连接管理,避免数据库连接泄漏 在较为完备的数据库连接池实现中,可根据预先的连接占用超时设定, 强制收回被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄漏。 ### 2.2 数据库连接池的参数设计 ### sql.DB 通过以下方法来配置maxOpen, maxIdle 和 maxLifeTime。 SetMaxOpenConns() SetMaxIdleConns() SetConnMaxLifetime() * 最大连接数maxOpen 最大连接数一般是((核心数 \* 2) + 有效磁盘数) * 最大空闲连接数maxIdle 默认情况下sql.DB,最多允许2个空闲连接保留在连接池中 * 当前总连接数 当前总连接数 = 当前空闲连接数 + 当前工作连接数 * 连接的最长时间maxLifeTime 超过这个时间, 连接被清理。 ### 2.3 获取连接,释放连接,清理连接 ### #### 2.3.1 获取连接: #### 分两种情况: * 工作连接数 < 最大连接数:表示用户有机会获取连接 * 当前连接数 >= 最大连接数:Connection 的创建达到了上限,用户只能等待重试工作连接数 在有机会获取连接条件下,又分为两种情况: * 如果空闲连接池的 size>0,直接从空闲连接池中获取连接 即空闲连接池中的弹出一个 Connection,把这个Connection 加入到工作连接池。 * 如果空闲连接池的 size=0,创建一个新的 Connection 给用户 #### 2.3.2 释放连接: #### 任何一个连接使用完毕之后需要归还给连接池,这也是数据库连接池实现中比较重要的逻辑, 通常还伴随着对连接的可靠性检测, 如果连接异常关闭,那么不应该继续还给连接池,而是应该新建一个连接进行替换。 如果空闲连接池未满,直接添加进去,并把工作连接池中相应的连接移除; 如果空闲连接池满了,直接close()掉,并把工作连接池中相应的连接移除。 #### 2.3.3 清理连接: #### 一个数据库连接无法保证长期有效, 例如,MySQL 侧会强制 kill 掉长时间空闲的连接(8h)。 在 sql.DB 中提供了 maxLifeTime 选项设置连接被复用的最大时间, 注意这个时间并不是连接空闲时间, 而是从连接建立到这个时间点就会被回收,从而保证连接活性。 ### 3. 最大连接数并不是设置的越大越好的原因 ### 1. cpu原因: 单核CPU的计算机也能“同时”运行数百个线程,但这只不过是操作系统用时间分片玩的一个小把戏。 一颗CPU核心同一时刻只能执行一个线程,然后操作系统切换上下文,核心开始执行另一个线程的代码, 以此类推。给定一颗CPU核心,其顺序执行A和B永远比通过时间分片“同时”执行A和B要快, 一旦线程的数量超过了CPU核心的数量,再增加线程数系统就只会更慢,而不是更快。 所以仅从CPU的角度来考虑,设置线程数等于CPU核数,能提供最优的性能。 2. 磁盘, 网络原因 磁盘,网络等因素。在I/O等待时间内,线程是在“阻塞”着等待磁盘, 此时操作系统可以将那个空闲的CPU核心用于服务其他线程,此时就产生了线程的切换, 所以,由于线程总是在I/O上阻塞,我们可以让线程/连接数比CPU核心多一些, 这样能够在同样的时间内完成更多的工作。 最终合理的连接数: 最大连接数 = ((核心数 \* 2) + 有效磁盘数)
还没有评论,来说两句吧...