HikariCP连接池初识
HikariCP的简单介绍
hikari-光,hikariCP取义:像光一样轻和快的Connetion Pool。这个几乎只用java写的中间件连接池,极其轻量并注重性能,HikariCP目前已是SpringBoot默认的连接池,伴随着SpringBoot和微服务的普及,HikariCP 的使用也越来越多。
在hikariCP github首页就放了一篇性能对比:
(https://github.com/brettwooldridge/HikariCP-benchmark)
看上去好像是碾压一众数据库连接池中间件。然而这个性能对比的有点老了,而且没有阿里自研的国产巅峰连接池druid的性能对比。我稍微看了下druid的github首页,star比hikariCP还多一点,druid在功能性上明显比hikariCP强。至于两者的性能谁更好,还引发过一次大佬间的口水战,目前没有看到有严格的性能对比报告。不过这不是我们这篇文章的重点···这篇文章只是为了稍微了解下hikariCP。
几个连接池参数
参数其实不多,挑几个重要的:
参数 | 含义 |
---|---|
minimumIdle | 这个属性控制着HikariCP尝试在连接池中维持的空闲连接的最小数量。如果空闲连接的数量下降至此值以下,并且连接池中的总连接数少于maximumPoolSize,HikariCP将尽最大努力快速而高效地添加额外的连接。然而,为了达到最大性能和对高峰需求的响应性,我们推荐不设置这个值,而是让HikariCP充当一个固定大小的连接池。默认值:与maximumPoolSize相同。 |
maximumPoolSize | 此属性控制池所能达到的最大大小,包括空闲和正在使用的连接。基本上,此值将决定到数据库后端的实际连接数的上限。合理的值最好由您的执行环境确定。当池达到此大小且没有可用的空闲连接时,调用 getConnection() 将会阻塞,直至 connectionTimeout 毫秒后超时。默认值:10 |
maxLifetime | 此属性控制池中连接的最大生命周期。正在使用中的连接永远不会被弃用,只有当它被关闭时才会被移除。为了避免池中发生大规模的连接消失,该属性会对每个连接适用轻微的负衰减。我们强烈推荐设置此值,并且应该比任何数据库或基础设施强加的连接时间限制短几秒。值为0表示无最大生命周期(无限生命周期),当然,这受到idleTimeout设置的约束。允许的最小值是30000毫秒(30秒)。默认值:1800000(30分钟)。 |
idleTimeout | 此属性控制连接在池中允许空闲的最大时间。此设置仅在minimumIdle被定义为小于maximumPoolSize时适用。一旦池达到minimumIdle连接数,空闲连接不会被回收。连接是否被视为空闲并回收,其最大变化范围为+30秒,平均变化范围为+15秒。一个连接在此超时前永远不会被视为空闲并回收。值0表示空闲连接永远不会从池中移除。允许的最小值是10000毫秒(10秒)。默认值:600000(10分钟)。 |
keepaliveTime | 此属性控制 HikariCP 将多频繁地尝试保持连接active,以防止它因数据库或网络基础设施而超时。这个值必须小于 maxLifetime 的值。"keepalive"操作仅会发生在空闲连接上。允许的最小值是30000毫秒(30秒),但最理想的值是在几分钟的范围内。默认值:0(禁用)。 |
keepaliveTime参数的设置应低于数据库空闲连接超时时间、TCP空闲连接超时时间以及一切其他设施的空闲超时时间。对于PostgreSQL来说,hikariCP的keepaliveTime参数应设置为小于PG库idle_in_transaction_session_timeout
的时间。
很明显,maximumPoolSize代表连接到数据库中的最大连接数。当然一般来说,真实场景中数据库中的连接数不会一直保持maximumPoolSize,因为应用不可能从始至终都是最高负荷运行。即使经过一个请求高峰期,根据idleTimeout或者maxLifetime的设置,那些空闲的连接经过一段时间后应该被释放。为了保证数据库的可用性,这个值应该设置为比数据库最大连接数小一些。比如PostgreSQL数据库,maximumPoolSize参应设置为小于PG库的max_connections
。这个参数还有调优空间,我们下面会提及。
minimumIdle是最小空闲连接数。例如,如果minimumIdle=100,数据库的active会话有10个,那么理论上数据库中的总连接数应该是100+10个。因为有可能有连接风暴的情况,真实的数据库连接应该比active+minimumIdle略多一点,但肯定小于maximumPoolSize。
为什么数据库连接数远大于minimumIdle?
理论上数据库总连接数只应该略大于minimumIdle,但是经过我实际观察连接池多节点的情况,哪怕数据库活跃连接只有10几个,数据库总连接数却远大于minimumIdle。观察pg_stat_activity的min(backend_start)、min(state_change),基本保持在maxLifetime左右,说明连接回收是有作用的。看上去新请求总喜欢启用新连接,而不是直接拿已有的idle连接用。个人猜多节点部署是原因之一,每个节点minimumIdle很低,也可能存在某些组件上的节点请求要多一点,瞬时请求数超过了minimumIdle从而创建了新的连接。第二,这跟maxLifetime参数也有关系,maxLifetime的目的是为了旋转连接,释放那些一直在用的连接,这样就存在那些使用过的链接需要一段时间来释放,并且最好不要再使用了,以免延长释放周期。
连接池大小设置
连接数过多的影响
在数据库的世界中,“数据库连接数的增多,数据库性能都会一定的下降”。
例如oracle的连接数对性能的影响,参考这个视频。当资源配置、jdbc并发都不变的情况下,连接数从2048下降到1024个,请求响应时间下降一半;如果连接数调整到96个,响应时间下降几十倍!!
连接数设置为多少才合适?
Unless you have a database server that has 1000 cores, it is very unlikely that you really want a maximumPoolSize of 2000.
除非你的数据库有1000C,不然你不应该有2000个连接。
最初始的情况下,数据库连接数应设置为cpu数,这样就能达到cpu的最大性能模式。但是这不是真实的。因为数据库的消耗不仅在cpu,也在磁盘和网络(也有内存、但相对影响不大)。例如,磁盘的读写也需要时间,cpu需要等待磁盘返回数据才可以进行下一步动作。在IO等待的这段时间(有可能时间很长),cpu最好是不要闲着,而是给其他进程使用。所以,基于磁盘等设备的等待时间,数据库连接数最好是高于cpu个数。
由于SSD等磁盘性能的提升,磁盘访问的速度是非常快的,也就是说IO等待时间下降,意味着连接数应该调整得更低。
调低了不能压榨CPU,调太高数据库性能损耗,那么到底调整到多少合适呢?hikariCP给出了这么一个公式
connections = ((core_count * 2) + effective_spindle_count)
其中core_count不应该计算超线程数;effective_spindle_count为主轴数,如果活动数据集完全被缓存,那么effective_spindle_count为零,随着缓存命中率的下降,它应该接近于实际的主轴数量。对应SSD还没有想过公式,不过可以肯定小于以上的最大值。当然这些都是理论值,实际情况要比这个更复杂,比如长连接问题,具体可参考连接池大小相关知识。
即使前端有10000个用户,连接池也不可能是10000个,即使是1000也太多了,需要一个更小的连接数,让其余的请求在连接池中等待,发挥数据库及其CPU的最佳性能才是最好的方式,参考连接数设置如上公式所示。
fixed pool
fixed pool是HikariCP的作者Brett Wooldridge的一个理念,是为了解决连接风暴问题。在minimumIdle参数解释中已经提及fixed pool:
为了达到最大性能和对高峰需求的响应性,我们推荐不设置minimumIdle,而是让HikariCP充当一个固定大小连接池(fixed size connection pool)。默认值:与maximumPoolSize相同。
把minimumIdle=maximumPoolSize就是fixed size connection pool。minimumIdle的默认值就等于maximumPoolSize。
其实早在2014年,Brett Wooldridge就提到了这个概念,参考PG社区邮件。这段话很重要,我将逐字翻译:
根据我的经验,即使是维护最小空闲连接数的池,在响应突发需求时也是有问题的。如果你有一个最大30个连接的池,并且有一个最小10个空闲连接的目标,突发的需求需要20个连接意味着连接池可以立即满足10个,但随后要尝试在应用程序申请连接时间到达connectionTimeout之前建立另外10个连接。这反过来在数据库上产生了突发需求,不仅减慢了建立连接本身,也减慢了实际上可能会将连接返回给连接池的事务。
现在,如果你的峰值是100个连接,你的中位数是50个,这并不重要。但我知道不少工作负载的峰值是1000,中位数是25,在这种情况下你会想要逐渐减少空闲连接。
最终我们采用了一个maxPoolSize + minIdle模型,默认情况它俩相等(fixed pool)。
虽然我不怀疑存在这样的工作负载(1000个活动连接),如果有人真的这么做了,我很想听听他们的理由。除非他们有超过128个CPU核和固态存储,否则基本上就是在白费功夫。
这也意味着,即使连接池的大小是固定的,你也想要旋转(rotate in and out)实际的会话,这样它们就不会无限期地挂着最大虚拟内存。
我们确实是这样做,有一个maxLifeTime设置来旋转这些连接。
在真实场景中,fixed pool对连接风暴影响的保护是可见的。fixed pool下,数据库的瞬时active连接突增,数据库的idle链接数下降,但数据库的总连接数不变,请求响应耗时影响不大。如果把maximumPoolSize设置为比minimumIdle大的一个值,连接风暴会造成瞬间产生很多新会话,而新会话的连接是非常消耗资源的,这明显增加了请求的响应时间。
连接泄露案例
由于本人不是连接池的专家,这里只是把最近找到的连接泄露资料小小汇总下。
连接泄露有如下现象:
-
“Connection is not available” exception。连接泄露,连接打满或者数据库因为active会话过度响应不过来了,新的请求会因为超过
connectionTimeout
时间而报错 -
Growth of active connections。数据库监控可以明显看到活动会话上涨
-
Application logs。应用日志也可以看到很多连接请求,包括活跃会话信息
-
Database views and logs。
pg_stat_activity
可以看到所有的会话状态和具体的sql,以及在log中可以看到新连接认证登录信息 -
HikariCP leak detection。需要打开
leakDetectionThreshold
,HikariCP可以检测链接泄露,这个参数默认是关闭的
对于定位连接泄露,应该
- 检查应用日志,特别是问题刚发生的时间点
- 合理的监控系统
- 善于debug、trace等hikariCP设置
- 设置
leakDetectionThreshold
参数
可能的原因:
- Misuse of streaming responses;
- Misuse of raw connections;
- Prolonged operations within
@Transactional
method (such as network invocation). - 配置错误,参考
- vitual thread,参考
References
https://github.com/brettwooldridge/HikariCP
https://github.com/brettwooldridge/HikariCP/issues/2148
https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
https://blogs.oracle.com/opal/post/always-use-connection-pools
https://mkyong.com/jdbc/hikaripool-1-connection-is-not-available-request-timed-out-after-30002ms/
https://medium.com/@eremeykin/how-to-deal-with-hikaricp-connection-leaks-part-1-1eddc135b464
https://medium.com/@eremeykin/how-to-deal-with-hikaricp-connection-leaks-part-2-847a9629627f
相关文章:

HikariCP连接池初识
HikariCP的简单介绍 hikari-光,hikariCP取义:像光一样轻和快的Connetion Pool。这个几乎只用java写的中间件连接池,极其轻量并注重性能,HikariCP目前已是SpringBoot默认的连接池,伴随着SpringBoot和微服务的普及&…...

LeetCode136只出现一次的数字
题目描述 给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。 解析 需要想到异或运算&#…...

html5实现端午节网站源码
文章目录 1.设计来源1.1 端午首页页面1.2 端午由来页面1.3 端午图集页面1.4 端午活动页面1.5 给我留言页面 2.效果和源码2.1 动态效果2.2 目录结构 源码下载 作者:xcLeigh 文章地址:https://blog.csdn.net/weixin_43151418/article/details/139524377 ht…...

echarts组件x轴坐标显示不全解决方法
1.旋转: 修改前: option {xAxis: {type: category,data: [Mon, Tue, Wed, Thu, Fri, Sat, Sun,Mon, Tue, Wed, Thu, Fri, Sat, Sun,Mon, Tue, Wed, Thu, Fri, Sat, Sun]},yAxis: {type: value},series: [{data: [120, 200, 150, 80, 70, 110, 130,120, 200, 150, 80, 70, 1…...
JS实现移动端的轮播图滑动事件
在移动端实现轮播图滑动事件,我们通常使用 touchstart、touchmove 和 touchend 这三个事件。下面是一个基本的示例,展示了如何使用原生JavaScript来创建一个简单的移动端轮播图滑动效果: HTML结构: <div id"carousel&qu…...

2024.6.10学习记录
1、代码随想录二刷 2、项目难点 review 3、计组复习...
RapidJSON
要在项目中使用 RapidJSON 库,需要首先下载并包含该库的头文件。以下是详细的步骤,包括如何下载、引用和使用 RapidJSON: 使用 CMake 引用 RapidJSON 如果你的项目使用 CMake 构建系统,可以按照以下步骤引用 RapidJSONÿ…...
二叉树的创建
目录 一、二叉树的定义 二、代码定义 三、遍历二叉树 1、前序遍历 2、中序遍历 3、后序遍历 四、方法的使用 一、二叉树的定义 二叉树(binary tree)是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。二叉树的递归定义为&a…...

adb shell进入设备后的命令
目录 一、查看删除手机 /data/local/tmp/下的文件 二、设置权限 三、查看手机设备正在运行的服务 四、可能需要的adb 命令 一、查看删除手机 /data/local/tmp/下的文件 可以通过以下命令: adb shell # 进入设备 ls /data/local/tmp/ # 查看文件夹下的内容…...
【Android面试八股文】Java中静态内部类是什么?和非静态内部类的区别是什么?
文章目录 Java中静态内部类是什么?和非静态内部类的区别是什么?这道题想考察什么?考察的知识点考生应该如何回答什么是内部类,什么是静态内部类?静态内部类非静态内部类静态内部类和非静态内部类的区别静态内部类和普通内部类都有各自的用途和优势扩展一:使用静态内部类来…...

IDEA启动项目报java.lang.OutOfMemoryError: GC overhead limit exceeded
idea编译项目时报j ava.lang.OutOfMemoryError: GC overhead limit exceeded错误,教你两步搞定! 第一步:打开help -> Edit Custom VM Options ,修改xms和xmx的大小,如下图: 第二步:File -> Settings…...

基于R语言BIOMOD2 及机器学习方法的物种分布模拟与案例分析
原文链接:基于R语言BIOMOD2 及机器学习方法的物种分布模拟与案例分析https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247606139&idx4&snf94ec30bfb5fa7ac0320403d49db3b66&chksmfa821e9ccdf5978a44a9ba96f6e04a121c0bbf63beea0940b385011c0b…...
【笔记2】Python编程:从入门到实践(第2版) - 埃里克·马瑟斯
第二部分 1、外星人入侵 Pygame包 2、数据可视化 Matplotlib 、Plotly 3、Web应用程序 Django 项目1:外星人入侵 第12章~第14章 使用Pygame包来开发一款2D游戏。 它在玩家每消灭一群向下移动的外星人后,将玩家提高一个等级。等级越高&…...

优质免费的 5 款翻译 API 接口推荐
当谈到翻译API时,我们通常指的是一种编程接口,它允许开发者将文本从一种语言翻译成另一种语言。这些API通常由专业的翻译服务提供商提供,如谷歌翻译 API、实时翻译API、腾讯翻译API、DeepL翻译API、Azure翻译API等。 这些API通常提供多种语言…...

雷电模拟器中控实现,直通源码
目录 前言 开发 需求 初始环境 UI搭建 功能实现 前言 本篇为易语言雷电模拟器中控项目实现操作,一般用于:脚本开发多线程模拟操作等起始模板框架,使用易语言原因为其前后端一体化,对于脚本开发而言更为方便。 开发 需求 以…...
从渲染管线到着色器Shader实践
浏览器渲染管线原理 浏览器渲染管线是浏览器将HTML、CSS和JavaScript转换为用户可见的网页的过程。这一过程涉及多个步骤,包括解析、布局、绘制和合成等。下面是浏览器渲染管线的详细原理: 解析(Parsing): HTML解析:浏览器下载HTML内容后,首先进行HTML解析,将HTML文本…...

LabVIEW开发实验室超导体电流特性测试系统
本系统旨在为学校实验室提供一个基于LabVIEW的超导体电流特性测试平台,通过精确测量超导体在不同温度和电流条件下的电学特性,帮助学生和研究人员深入理解超导体的物理性质。本文将从背景、目标、工作原理、使用方法、操作流程和注意事项等方面详细介绍该…...

C语言之main函数的返回值(在linux中执行shell脚本并且获取返回值)
一:函数为什么要返回值 (1)函数 在设计的时候是设计了参数和返回值,参数是函数的输入,返回值是数据的输出 (2)因为函数需要对外输出数据(实际上是函数运行的一些结果值)…...
【手撕面试题】Vue(高频知识点五)
每天10道题,100天后,搞定所有前端面试的高频知识点,加油!!!在看文章的同时,希望不要直接看答案,先思考一下自己会不会,如果会,自己的答案是什么?想…...
C#有哪些方式实现回调函数、处理异步操作或响应某些条件时的动作
在C#中,除了使用event关键字来定义事件和回调函数(事件处理器)之外,还有几种其他方式来处理异步操作或响应某些条件时的动作: 委托(Delegates): 委托类似于C/C中的函数指针&#x…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...