标签:springboot 数据库 40 转帖 idle 线程 lifetime Hikari 请求
<div id="content_views" class="htmledit_views">
<p>yml 配置<br><img alt="" height="235" src="/i/ll/?i=7724916bc5d449b48114ed52462ba48d.png" width="517"></p>
- minimum-idle:10
该参数限制数据库连接池保持数据连接的最小数量,如下当我们启动服务时,不做任何请求,服务就会默认建立10个数据库连接。等到有需求的时候就可以及时使用。
我们启动服务不做任何请求可以看到数据库与服务的连接数就是10. 且状态都为sleep.
这里记录一个问题,假设有这样一个分布式微服务服务(campus-sign-up-service), 该服务hikari配置如第一张图,如果该服务有2实例,那么这两个实例的最小连接数分别是10,还是公用配置总共为10呢?答案是分别为10,每个实例都会单独按照上面的配置去建立连接。
这里我们启动两个实例在去查看一下数据库中的连接数量,可以发现实例数量变为2*10=20.
- maximum-pool-size:40
该配置意为在同一时间应用向数据库连接池请求的数连接超过最小连接数时,将根据需求扩大数据库连接数,但是该链接数的上线是maximum-pool-size的值,如这里的40。当请求超过最大连接数时,进入等待队列,直到有空闲的连接。
如下我们创建80个线程去执行业务逻辑计算和数据库请求。 public AddCourseEntity studentBookCourse(AddCourseEntity addCourseEntity) {
Date startTime=StudentUtil.getDateTime();
System.out.println("Start Time:" + startTime);
for(int i=0;i<=80;i++) {
Thread thread= new Thread(()->{
studentHandler.longTransactionTest(addCourseEntity);
});
thread.start();
}
return addCourseEntity;
}
为了保证请求数据库的线程数在同一时间一定大于40,我们在其中一个事务里面再睡60s。(当然真实开发过程中,要避免将耗时的业务逻辑处理加入事务中,长事务会长时间占用其申请到的数据库连接线程,造成极大浪费。当大量请求进来时,数据库链接被消耗完迟迟不能释放,就会阻塞其他请求或是导致其他请求因申请不到数据库链接池中的连接线程而超时失败。如下代码,开始时线程休眠,但是只要运行进入@Transactional 注入的方法,就已经占用数据库资源了,不论这个时候是否开始了数据库的相关操作。最极端的情况,如下我们只保留休眠代码,和数据库操作相关的代码都删除,这个事务方法一样的从方法开始就会占用数据库连接池里面的一个线程) @Transactional
public void saveInfoAndTableA(AddCourseEntity addCourseEntity) throws InterruptedException {
Thread.sleep(60*1000);
TableA tableA = new TableA();
StudentUtil.assembleTableA(addCourseEntity, tableA);
tableARepository.save(tableA);
addCourseEntity.setTableAId(tableA.getId());
}
经过测试我们可以统计到数据库的连接已经达到最大链接数40。
总共有80个线程在请求,剩余的40个请求线程就被迫处于等待状态。
- connection-timeout: 20000 链接上一个测试结果接续说明,当剩余的40个请求线程等待数据库连接池中释放线程时间超过20s,请求线程就开始报错了
- max-lifetime: 50000
idle-timeout: 10000
如上两个参数我要连着一起总结,官方网站对这两个参数的解释分别如下:
max-lifetime: This property controls the maximum lifetime of a connection in the pool. An in-use connection will never be retired, only when it is closed will it then be removed. On a connection-by-connection basis, minor negative attenuation is applied to avoid mass-extinction in the pool. We strongly recommend setting this value, and it should be several seconds shorter than any database or infrastructure imposed connection time limit. A value of 0 indicates no maximum lifetime (infinite lifetime), subject of course to the idleTimeout setting. The minimum allowed value is 30000ms (30 seconds). Default: 1800000 (30 minutes)
idle-timeout: This property controls the maximum amount of time that za connection is allowed to sit idle in the pool. This setting only applies when minimumIdle is defined to be less than maximumPoolSize. Idle connections will not be retired once the pool reaches minimumIdle connections. Whether a connection is retired as idle or not is subject to a maximum variation of +30 seconds, and average variation of +15 seconds. A connection will never be retired as idle before this timeout. A value of 0 means that idle connections are never removed from the pool. The minimum allowed value is 10000ms (10 seconds). Default: 600000 (10 minutes)
max-lifetime: 最小允许值30s 默认值:30min
This property controls the maximum lifetime of a connection in the pool: 这句话的意思是如果当前链接处于空闲状态,且存活时间超过设定的最大存活时间,就会关闭这个链接,并根据设置判定是否再启动新的连接。
idle-timeout: 最小允许值10s 默认值:10min
测试总结:对于这两边我不再展示测试过程,而直接写测试结果(如下结果都是经过反复测试)。
case 1:配置max-lifetime:50s 而idle-timeout:1s
显然idle-timeout配置错误小于了其最小允许值,框架将自动使用默认值10min。当我们同时启动40个线程请求,每个需要执行1min,显然单个线程执行时间已经超过了max-lifetime设置的50s,这个时候这40个线程可以成功执行,在40个请求线程都执行完成后不再发起新的请求,数据的这40个链接什么时候释放到最小链接数10呢? 答案是10min后。
case2:配置max-lifetime:50s 而idle-timeout:1s
同样是case1中的条件,但是我们将测试用例中的单个线程需要执行1min,修改为20s,并且在40个请求线程都执行完成后不再发起新的请求,那么多余的线程多久后释放呢?答案是30s(50s-20s)后,数据库连接数由40降到10.
case3:配置max-lifetime:50s 而idle-timeout:1min
如果有40个请求线程,每个如case1中执行1min, 由于执行时间已经超过了max-lifetime的设置,这个时候如果后续不来新的请求,那么多余的线程就按照idle-timeout设置的合理时间去清理多余线程,也就是1min。 总结:max-lifetime是根据请求线程自身情况计算清理时间,重请求线程自身去设定的释放限制,idle-timeout是对所有请求线程进行的统一限制。 每个请求都要遵循这两个原则去关闭。由两个原则计算出来的最近时间去判断是否释放请求所占有的数据个链接。
这里记录一个额外的问题,minimum-idle: 闲时大小的设置是否会消耗我们服务的线程。
1. minimum-idle:100
2. minimum-idle:5
从而可以得出结论,数据的连接池数量,应该是由hikri的统一管理的,并不会因为闲时线程数量的设置变大,而而外的消耗我们服务的线程资源。
文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览147289 人正在系统学习中
标签:springboot,
数据库,
40,
转帖,
idle,
线程,
lifetime,
Hikari,
请求
From: https://www.cnblogs.com/jinanxiaolaohu/p/18256046