背景
- 外包-项目经理-客户-质量失控
- 请求处理慢,狮山代码卡死连接吃满了,再多配点?CN扛不住了死了。
- 发现公司B域项目配的一直挺随意的,就优化性能和配置调优2手抓了
参数
maxWait
- 默认 -1 永久等待我滴龟龟
- 一般建议配置:10000 快速失败
minIdle
- 最小空闲连接数量,顺利运行暖机后的,保底的连接持有数量;
- 但也不是真保底,如果大于容忍时间(就是你闲的太久了,也会杀到小于minIdle的连接量)
- 一般建议配置:1 或 同maxActive
- 因为做好暖机,后面就交给业务吧,如果业务都没有打进来,那该杀杀别给数据库上强度,尤其现在国产化,不利于稳定的事不要做。
- 当然你也得考虑实际业务场景,如果是一波一波大流量,那就要配置的大一些长期持有(或者时间节点前主动暖机),具体多大需要结合数据库CN能力+业务模型+节点数量+期望请求时间综合考虑了。
- 说人话,如果有能力压测就看压测结果,达到峰值性能实时的active量,是多少我们就初始化&&minIdle多少
- 这个话题就散了,因为“峰值性能”还意味着要符合设计峰值性能,从设计到验收的过程鸡生蛋蛋生鸡
- 从设计开始应该就估算过多少实例每个要承载多少请求,正向的也一起估过主机配置/数据库资源量,都是要钱的,数据库资源就包括承载多少链接,分给每个实例可以多少即使有冗余那也是有数的;主机配置包括核数,可估算并发量/QPS
- 所以实际连接数设置分2步,第一步纯落地建设的估算/经验数据,获得大致数据;第二步是上线前的压测调整,符合预期最好,达不到就要优化代码或调整配置
- 估算还是必要的
- 单说说不清楚,后面项目落地流程整体说吧
- 这个话题就散了,因为“峰值性能”还意味着要符合设计峰值性能,从设计到验收的过程鸡生蛋蛋生鸡
initialSize
- 初始连接
- 一般建议配置:咨询根据实际数据库CN节点抗压能力和你的应用数来
maxActive
- 最大连接
- 一般建议配置:咨询根据实际数据库CN节点抗压能力和你的应用数+业务模型来
- Min(0.6* 数据库CN节点数量* 单CN最大支持连接/应用实例数,1.5 *应用实例核心数/DBIO时间占比)
- 其中数字系数为经验冗余
- 如何获得DBIO?
- 1、抽查并分析典型接口:土法计算
- 2、等压测:RT开始下降时,100% - 1 / QPS / (1000ms/RT ms) 即为
- 比如:1C2G的实例,DBIO占20%,仅从应用实例需求来讲,只需要配5 * 1.5 = 8,配多了浪费
实际上 建议maxActive/minIdle/initialSize 三位一体,配置相同。min/maxEvictableIdleTimeMillis容忍空闲亦配置相同
降低复杂性,及时释放连接,按照业务特化指定时机主动暖机
minEvictableIdleTimeMillis
- 最小超过__时间可考虑失效此连接
- 超过这个时间,并且持有连接数大于minIdle,就会考虑杀掉连接;
- 一般建议配置:默认 60 * 60 * 1000
- 因为暖机后维持稳定运行,就不该存在杀连接的场景,max和min配一样,业务特化才是最好的,通用的不靠谱。
- 一般根本做不到,分析什么时间并发分布,再分析个min和max。
- 首先你可以做到提前暖机(在服务时间明确时)
- 而且外面有云平台先抗压流量打到分散节点,这都不够零散请求导致的扩容耗时,那还是寄了吧。
maxEvictableIdleTimeMillis
- 英文命名有歧义,实际是最大容忍空闲时间
- 超过这个时间的空闲,就不管你够不够minIdle了,都鲨啦
- 一般建议配置:同min 60 * 60 * 1000
- 就和JVM Xmx Xms一样,伸缩个棒棒锤
phyTimeoutMillis
- 理论上是最高优先级,连接存活超过这个时间一律杀
- 实操中建议咨询数据库厂商他们的连接有效时间最长多久(不管活不活跃)
- 一般建议配置:咨询厂商
validationQuery
- 一般建议配置:select 1 / select 1 from dual;
- 以数据库版本为准,一定要显式配置声明消除歧义
- 看到这个我就想笑,总监摇人摇来个T4,赶鸭子集成个审批流进来,结果数据源源码报错都不会看(Atomic数据源),胖哥哥简单看个几十分钟就找到了是因为log.trace日志级别的日志: validate sql执行的异常被吞了。这数据源比较严格必须validate通过才行。
timeBetweenEvictionRunsMillis
- 多久检测一次空闲时长
- 一般建议配置: 默认60 * 1000 性能影响忽略不计
testWhileIdle
- 对,数据源是提供了配置项,但不一定非得用上,食之无味弃之可惜
- 如果你的业务场景长期稳定被调用,那根本走不到被扫描空闲时长达标(timeBetweenEvictionRunsMillis默认1分钟),然后触发test
- 如果你的业务场景一波波,那你该考虑及时释放资源(连接),比如控制上面的min/maxEvictableIdleTime
- 一般建议配置: 默认true
testOnBorrow
- !!充满歧义的命名,borrow->借,实际根本不是借,而是take->取/占有连接池中已有连接。
- 当我们的代码取需要use数据库连接时,先take一个连接出来,没有就建,take的时候要不要test下可用?
- 一般建议配置:性能影响大 默认false
testOnReturn
- borrow是take,这里就是用完了还时要不要也test?
- 所以同理
- 一般建议配置:性能影响大 默认false
poolPreparedStatements
- 各类框架说到底还是要把仓储转基础的sql statement的,所以有这个参数配是否缓存ps
- 搜索了下,有几个顾虑点:
大模型说:
事实上呢?
线程不安全是无稽之谈他是connection独享的: com.alibaba.druid.pool.DruidConnectionHolder#statementPool
oracle确实有特殊处理,但是是关闭oracle的一些隐式缓存防止意外,没看到游标在哪。
所以说,大模型仅供参考,一切以实际代码为准。大模型会毁了新程序员的脑子的。
- 是否开启取决于你的应用sql量多少?容器内存给到多少?
- 一般C域的话,微服务相对纯净职能明确,SQL不会很多,如果响应时间敏感是可以开启的。
- 一般B域M域的话,即使工程老旧乱炖,但是内存给足,也是可以开启的,毕竟sql没那么多说到底,crud才是主旋律,内存主要就给crud用合理。
- 一般建议配置: 不敢建议,我是开了
- 实现原理:老生常谈八股文: 继承LinkedHashMap,重写removeEldest方法
maxPoolPreparedStatementPerConnectionSize
- 如果开启了缓存ps,最大缓存几个?
- 默认10个,注意是每个连接connection都持有10个容量的缓存。
- 连接数量:书接开头最开头的maxActive和minIdle,上面建议直接配成一致的,避免伸缩带了不确定性,那么这里就可以
- 1C2G实例给了8的maxActive,那么其实可以调到100!8 * 100 也不吃多少内存。
- 一般建议配置:加大药量 100!
maxOpenPreparedStatements
- 原则上是一个connection最大同时开启多少个ps,默认-1
- 实际上源码未使用
- 一般建议配置: 不配/-1
removeAbandoned、removeAbandonedTimeoutMillis
- 字面意思是移除废弃连接和阈值时间
- 实际呢?判定条件是
(currrentNanos - pooledConnection.getConnectedTimeNano())/ (1000 * 1000) >= removeAbandonedTimeoutMillis
而这个getConnectedTimeNano来自获取连接时设置
-
那现在已知判定条件,你还知道不会有人直接用连接,都是持久化框架,你认为持久化框架会即用即建吗?
- 当然不会,这就是重复建设,每个轮子都做自己的缓存/算法/holder。实际更应定性为职责不清,池子就在当前大环境下就该做好池子(类似于线程池)的本分,Manage的部分交给更高级的框架。
- 但没人能开天眼,不是错误是历史问题。
-
一般建议配置:不开启,除非你直接用dataSource获得连接比较基础的应用。
监控配置
- 一般建议配置: 不开启
- 现在都打agent做链路分析了,你一个小数据源时代过去了,大杂烩<各司其职
- 及时没有现成平台你搭个也好