• 连接池一般对外提供获得连接、归还连接的接口给客户端使用,并暴露最小空闲连接数、最大连接数等可配置参数,在内部则实现连接建立、连接心跳保持、连接管理、空闲连接回收、连接可用性检测等功能。

image.png

  • 业务项目中经常会用到的连接池,主要是数据库连接池、Redis 连接池和 HTTP 连接池

注意鉴别客户端 SDK 是否基于连接池

客户端的常见三种模式:

  • 连接池和连接分离的 API:有一个 XXXPool 类负责连接池实现,先从其获得连接 XXXConnection,然后用获得的连接进行服务端请求,完成后使用者需要归还连接。通常,XXXPool 是线程安全的,可以并发获取和归还连接,而 XXXConnection 是非线程安全的。对应到连接池的结构示意图中,XXXPool 就是右边连接池那个框,左边的客户端是我们自己的代码。
  • 内部带有连接池的 API:对外提供一个 XXXClient 类,通过这个类可以直接进行服务端请求;这个类内部维护了连接池,SDK 使用者无需考虑连接的获取和归还问题。一般而言,XXXClient 是线程安全的。对应到连接池的结构示意图中,整个 API 就是蓝色框包裹的部分。
  • 非连接池的 API:一般命名为 XXXConnection,以区分其是基于连接池还是单连接的,而不建议命名为 XXXClient 或直接是 XXX。直接连接方式的 API 基于单一连接,每次使用都需要创建和断开连接,性能一般,且通常不是线程安全的。对应到连接池的结构示意图中,这种形式相当于没有右边连接池那个框,客户端直接连接服务端创建连接。

  • Jedis 的 API 实现的是池和连接分离的方式

  • Apache HttpClient 是内置连接池的 API
  • Hikari 是内部带有连接池的

    使用连接池务必确保复用

QPS 每秒查询率(Query Per Second)
TPS 吞吐量 Throughput
RT 响应时间

连接池的配置不是一成不变的

  • 连接池参数配置中,最重要的是最大连接数,许多高并发应用往往因为最大连接数不够导致性能问题。
  • 但,最大连接数不是设置得越大越好,够用就好。
  • 需要注意的是,针对数据库连接池、HTTP 连接池、Redis 连接池等重要连接池,务必建立完善的监控和报警机制,根据容量规划及时调整参数配置。
  • Spring默认Hikari连接池

思考和总结

自从spring boot 2.x版本后,有较大的改动:

  • 默认的redis的链接池从JedisPool变成了LettucePool,Lettuce主要利用netty实现与redis的同步和异步通信。所以更安全和性能更好;
  • 默认的数据库连接池也变更为HikariCP,HiKariCP 号称是业界跑得最快的数据库连接池,HiKariCP 官方网站解释了其性能之所以如此之高的秘密。微观上 HiKariCP 程序编译出的字节码执行效率更高,站在字节码的角度去优化 Java 代码,HiKariCP 的作者对性能的执着可见一斑,不过遗憾的是他并没有详细解释都做了哪些优化。

    宏观上主要是和两个数据结构有关,一个是 FastList,另一个是 ConcurrentBag。 FastList是对Java List的增强,HiKariCP作者认为Java SDK的List在其使用场景下比较慢,因此在SDK提供的List(ArrayList的remove)的基础上做了增强;

ConcurrentBag是对Java并发集合的增强, 通过 ThreadLocal 做一次预分配,避免直接竞争共享资源,非常适合池化资源的分配。