一、引子

合理配置一个应用的数据库参数,使其运行良好,这很重要。本文以某务中台的生产环境为例,从Apollo上拔下来一套配置,分析是否合理。

二、MybatisPlus配置

由于我们使用Apollo配置参数,所以分两部分:1.个体配置 2.全局配置

2.1 mybatisplus个体配置

mybatis-plus.mapper-locations = classpath*:/mapper/*Mapper.xml  mapper文件地址匹配
mybatis-plus.type-aliases-package =xx.po 映射的实体包路径,
mybatis-plus.tenant-config.ignoretable = table1,table2
mybatis-plus.auth-config = []
mybatis-plus.global-config.sql-parser-cache = true 缓存sql解析

2.2 mybatis-plus全局配置

mybatis-plus.mapper-locations = classpath:/mapper/*Mapper.xml  mapper文件地址匹配
mybatis-plus.configuration.map-underscore-to-camel-case = true    下划线转驼峰
mybatis-plus.global-config.logic-delete-value = true  逻辑已删除值
mybatis-plus.global-config.logic-not-delete-value = false  逻辑未删除值
mybatis-plus.max-query-records-size = 10000

三、Datasource配置

3.1 dataSource个体配置

=========数据库配置=========
spring.datasource.connectionProperties = druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 通过connectProperties属性来打开mergeSql功能;慢SQL记录5秒

spring.datasource.type = com.alibaba.druid.pool.DruidDataSource 使用德鲁伊连接池
spring.datasource.driver-class-name = org.postgresql.Driver 驱动类名
spring.datasource.url = xx  数据库连接url
spring.datasource.username = ${dbUserName} 用户名
spring.datasource.password = ${dbPassword} 密码
spring.datasource.minIdle = 5 最小空闲连接数 5
spring.datasource.initialSize = 5 初始连接数 5
spring.datasource.maxActive = 100 最大连接数
spring.datasource.maxWait = 60000 获取连接等待超时的时间 60s=1分钟

spring.datasource.filters = stat,wall 监控统计拦截,用于监控界面sql统计
spring.datasource.poolPreparedStatements = false 是否启用缓存PreparedStatements  
spring.datasource.maxPoolPreparedStatementPerConnectionSize = 20 指定每个连接上preStatement缓存数---》未生效!!!

=========健康检查=========
spring.datasource.validationQuery = SELECT 1 连接池的健康检查SQL
spring.datasource.testOnBorrow = false 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
spring.datasource.testOnReturn = false 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
spring.datasource.testWhileIdle = true 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。

#每timeBetweenEvictionRunsMillis毫秒检查一次连接池中空闲的连接,把空闲时间超过minEvictableIdleTimeMillis毫秒的连接断开,直到连接池中的连接数到minIdle为止
spring.datasource.minEvictableIdleTimeMillis = 300000 最小可驱逐空闲时间,连接保持空闲而不被驱逐的最长时间,单位是毫秒 300s=5分钟
spring.datasource.timeBetweenEvictionRunsMillis = 60000 间隔多久才进行一次驱逐检测,单位是毫秒 60s=1分钟

=========连接超时=========
# 关闭abanded连接时输出错误日志,预生产/生产不建议开启,对性能影响
spring.datasource.logAbandoned = false
# 是否清除已经超过“removeAbandonedTimout”设置的无效连接。
spring.datasource.removeAbandoned = true 
# 连接超过指定时间未关闭,就会被强行回收 180s=3分钟
spring.datasource.removeAbandonedTimeoutMillis = 180000

四、源码剖析

看完配置,大家心里还是懵逼对吧,参数如何生效,druid到底如何运行?

下面,带着问题,深入源码,直接剖析druid如何申请连接、释放连接、连接泄露检查。

4.1.申请连接

最终跟进到DruidDataSource的getConnectionDirect(long maxWaitMillis),获取得到连接后,validationQuery有效性检查,源码如下:

1.testOnBorrow =true,先直接校验,执行validationQuery,失败就关闭连接JdbcUtils.close(realConnection);

2.testWhileIdle=true,如果testOnBorrow =false, 测试空闲的连接,执行validationQuery,失败就关闭连接JdbcUtils.close(realConnection);

3.removeAbandoned=true,如果开启了泄露回收:把连接添加进Map<DruidPooledConnection, Object> activeConnections 。供泄露回收时使用。

分支1和2只会有一个执行。

4.2.释放连接

德鲁伊连接池在获取连接时,会调用一次DruidDataSource的init()。方法中createAndStartDestroyThread()开启了一个销毁线程。

销毁连接的线程包含了run(),如下:

在一个for空条件循环中,根据配置的timeBetweenEvictionRunsMillis连接检测间隔时间,执行一次DestroyTask.run()就休眠一次间隔时间。未设置默认60s。(实际源码中定义了60spublic static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = 60 * 1000L;,所以用户未设置,默认60s,上图中else分支sleep1秒不会执行到)

追踪DestroyTask.run()如下:

2个步骤:

  1. shrink()收缩校验
  2. removeAbandoned()连接泄露移除

shrink()收缩校验

DruidDataSource内部定义了DruidConnectionHolder[] 类型的3个数组:

  • 1.connections:可用连接数组。申请连接就从这里数组队尾拿连接。
  • 2.evictConnections:待移除连接数组。
  • 3.keepAliveConnections:待保活检测数组。

塞进数组

shrink()中计算出需要校验的数量checkCount,执行收缩校验核心逻辑:

  • 校验物理连接的超时时间phyTimoutMills:超时放入evictConnections中,等待移除。
  • 空余时间大于minEvictableIdleTimeMillis(受保最小空闲时间),并且索引(poolingCount)小于checkCount的连接则放入evictConnections;
  • 空余时间大于minEvictableIdleTimeMillis(受保最小空闲时间),并且索引大于checkCount的连接,假若空余时间大于maxEvictableIdleTimeMillis则放入evictConnections,否则放入keepAliveConnections中进行keepAlive检测。

如下图:

数组处理

1.evictConnections:待移除连接数组。使用JdbcUtils.close()  关闭连接。

2.keepAliveConnections:待保活检测数组。根据配置的validationQuery查询SQL执行连接可用性校验。校验通过后再put(holder)塞进connections可用连接数组。

4.3.泄露连接移除

如果开启了removeAbandoned ,执行removeAbandoned()。移除泄露连接逻辑如下:

实际上,就是对可能的连接泄露(打开连接后长时间不关闭)兜底。

1)遍历活跃连接Map<DruidPooledConnection, Object> activeConnections。

2)跳过运行中的连接,running定义:执行SQL前赋值true ,执行完后置false。---》问题1得到答案,不会暴力关闭执行中的连接。

3)如果当前连接已连接时间>=removeAbandonedTimeoutMillis ,直接从activeConnections map 中移除。

这里消耗性能主要两步骤:

  • 1.内存中记录+移除泄露连接
  • 2.打印相关日志的IO---》logAbandoned=false 可关闭写日志

spring 的druid 连接池一般不会造成泄露。如果出现连接泄露,应该找到问题解决。---》问题2得到答案,目前关闭了写日志,就剩下了第一点“内存占用+过滤的性能”成本,要求不高的场景可以作为兜底方案使用。如果项目已稳定,推荐关闭。

五.分析&总结

本节为我们根据:申请、释放连接相关的参数配置,剖析策略是否合理。

5.1 配置分析

spring.datasource.testOnBorrow = false 申请连接时执行validationQuery检测连接是否有效

spring.datasource.testOnReturn = false 归还连接时执行validationQuery检测连接是否有效

spring.datasource.testWhileIdle = true testOnBorrow=false时才生效,申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。

spring.datasource.initialSize = 5 初始连接数 5

spring.datasource.maxActive = 100 最大连接数

spring.datasource.minIdle = 5 最小空闲连接数 5

timeBetweenEvictionRunsMillis= 60000 60s=1分钟检测一次

minEvictableIdleTimeMillis=300000 300s=5分钟 最小空闲不移除时间

maxEvictableIdleTimeMillis 未设置最大空闲移除时间,默认DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 60L * 7 = 7小时。

keepAlive: 未设置保活开关,默认false关闭。不执行保活测试策略。

上述配置对应的策略:

1.初始策略

初始5个连接,最多可开启100个连接。

2.申请策略

申请连接的时候检测,如果连接空闲时间大于1分钟(检测间隔时间),执行validationQuery检测连接是否有效。---》这里可确保我们空闲时间超过1分钟的连接,校验后使用。

3.回收策略

每一分钟执行一次检测,策略如下:

1.连接空闲小于5分钟,不移除。

2.连接空闲大于5分钟,保留”minIdle设置的5个idle连接”,可移除(总数-5)个连接。

3.连接空闲大于7小时,可移除“minIdle设置的5个idle连接”。---》因为没有设置maxEvictableIdleTimeMillis ,默认空闲7小时后才会移除。不过一共就5个倒也没什么事。

4.连接空闲5分钟~7小时,由于没开启keepAlive保活开关,无法对“minIdle设置的5个idle连接”保活测试。-->minIdle设置的5个idle连接,这段时间一直不回收,也不做保活测试,连接是否有效无法保证。

5.2总结

1.现有项

removeAbandoned=true 开启连接泄露检测,要求不高的场景可以作为兜底方案使用。如果项目已稳定,推荐关闭。

2.可添加项

phyTimeoutMillis:看需要开启。物理超时时间。不管空闲时间,超时直接移除。---》这个是终极兜底方案,可以确保超时强制移除。

maxEvictableIdleTimeMillis:建议开启,实现精细化控制。

keepAlive: 建议开启。可针对“minIdle设置的空闲连接”,进行保活测试,从而提升连接的质量。

postgreSql最佳配置详解(connection 申请、回收策略)的更多相关文章

  1. druid 参数配置详解

    druid 参数配置详解 */--> druid 参数配置详解 Table of Contents 1. 初始化连接 2. 参数配置及说明 3. 注意事项 3.1. 底层连接 3.2. 空闲检查 ...

  2. 阿里云slb和ucloud负载均衡ulb添加ssl证书将http服务https化的配置详解

    阿里云和ucloud服务器配置ssl证书将http服务https化的配置详解 项目背景: 苹果App于2017年1月1日将启用App Transport Security安全功能,即强制App通过HT ...

  3. Tomcat记录-tomcat常用配置详解和优化方法(转载)

    常用配置详解 1 目录结构 /bin:脚本文件目录. /common/lib:存放所有web项目都可以访问的公共jar包(使用Common类加载器加载). /conf:存放配置文件,最重要的是serv ...

  4. tomcat常用配置详解和优化方法

    tomcat常用配置详解和优化方法 参考: http://blog.csdn.net/zj52hm/article/details/51980194 http://blog.csdn.net/wuli ...

  5. [转]阿里巴巴数据库连接池 druid配置详解

    一.背景 java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,又不得不使用数据库连接池.数据库连接池有很多选择,c3p.dhcp.proxool等,druid作为一名后起之秀,凭借其出色 ...

  6. redis配置详解

    ##redis配置详解 # Redis configuration file example. # # Note that in order to read the configuration fil ...

  7. JSHint配置详解

    Also available on Github JSHint配置详解 增强参数(Enforcing Options) 本类参数设为true,JSHint会产生更多告警. bitwise 禁用位运算符 ...

  8. 日志分析工具ELK配置详解

    日志分析工具ELK配置详解 一.ELK介绍 1.1 elasticsearch 1.1.1 elasticsearch介绍 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分 ...

  9. springdata+redis配置详解

    springdata设计初衷是位简化数据类型和数据的持久化存储,它并不局限是关系型数据库还是nosql数据库,都提供了简化的数据库连接,让数据获取变得更加的简单.所有这些的实现有统一的api提供. 本 ...

  10. CentOS6.5下VNC Server远程桌面配置详解

    参考文献: (总结)CentOS Linux下VNC Server远程桌面配置详解 远程桌面连接工具VNC——license Key 我的下载地址为 太平洋下载 VNC连接黑屏的问题 centos 6 ...

随机推荐

  1. Linux 统计Web服务日志命令

    本人在Linux运维中收集的一些通用的统计,Apache/Nginx服务器日志的命令组合. Apache日志统计 # 列出当天访问次数最多的IP命令 [root@lyshark.cnblogs.com ...

  2. automapper 10 +autofac+asp.net web api

    automapper 不必多说 https://automapper.org autofac 这里也不多说 https://autofac.org 这里主要 说 automapper 10.0 版本+ ...

  3. 使用Visual studio code 进行.NET 开发

    Visual studio code 作为一款强大的编辑器,相信很多开发者都用过.vs code 的强大源自开源生态丰富,编辑器本身简单,但是加上各式的插件,就变得无比牛逼,基本可以替代现有的大部分工 ...

  4. SpringBoot实现统一异常处理

    目录 前言 实现步骤 定义统一响应对象类 定义业务异常枚举接口和实现 定义业务异常基类 定义全局异常处理切面 测试和验证 总结 前言 近日心血来潮想做一个开源项目,目标是做一款可以适配多端.功能完备的 ...

  5. Excel-批量填充数字

    1.一般情况下,都是使用鼠标左右键拖动来实现数据的填充的 2.但是填充1200列,下拉拖动就非常麻烦,可以首先定位到A200. 在屏幕左侧中央处找到剪切板下方的"A1"字样,鼠标单 ...

  6. 建立DNS隧道绕过校园网认证

    建立DNS隧道绕过校园网认证 因为之前在本科的时候破解过校园网三次,主要就是利用其业务逻辑上的漏洞.53端口未过滤包.重放攻击的手段,然后就是一个博弈的过程,这三次加起来用了大概有一年的时间就被完全堵 ...

  7. 如何设置mysql root密码

    如何设置mysql root密码: 1.首次安装 root初始密码为空,注意就是没有密码,直接敲回车即可进入 D:\wamp\bin\mysql\mysql5.6.17\bin> mysql - ...

  8. CentOS 7 SSH连接超时自动断开解决方案

    用SSH登录到Linux的时候,由于默认的连接超时时间很短,经常断开! 1.修改文件 # vi /etc/ssh/sshd_config # vi /etc/ssh/sshd_config 找到 #C ...

  9. 高并发时为什么推荐ReentrantLock而不是synchronized

    目录 1.最初的 synchronized 2.synchronized 的优化 3.但是,JAVA的最终答案 JDK 21 LTS 来了 1.最初的 synchronized 它默认对临界资源添加重 ...

  10. 7zip 命令行压缩指定后缀名

    接到一个需求,就是测试同学在测试软件的指定功能时,可能需要调试版本来查看输出信息,所以我们需要使用一个批处理文件来快速生成一个 debug 压缩包 7zip 给出了很多有用的命令行,我们可以使用它指定 ...