连池都不会配,你的服务不炸算我输
面试的时候问候选人:"你的服务连接MySQL,timeout设多少?"
十个人里有九个会说:"啊?什么timeout?我用的HikariCP,默认的。"
好,很好。这个"默认的"在本地跑起来美滋滋,上了生产就开始表演什么叫"薛定谔的可用性"——看起来好好的,实际上随时给你来个雪崩。
默认配置就是个坑
你以为Druid/HikariCP这些连接池框架的开发者是傻子吗?人家把默认连接数设成10、timeout设成30秒,是有讲究的——这是给"本地开发"看的,不是给"生产环境"看的。
我见过最离谱的一个案例:有个哥们儿用Spring Boot写了个API服务,连接池默认10个连接,然后在前端加了个"加载动画,等待中..."的交互。结果呢?
并发一高,10个连接瞬间被占满,新的请求排队等着超时。用户以为服务挂了,疯狂刷新,越刷新连接越不够用,最后MySQL直接报"too many connections",整个服务原地升天。
这不是个例,这是行业冥灯行为。
连接池的本质:你到底在池里放了多少水?
先把几个核心概念讲清楚,别到时候调参跟开盲盒似的。
最大连接数(maximumPoolSize):这个不是越大越好。你MySQL最大连接数是多少?默认151,你连接池设200,那连接池拼命建连接,MySQL直接拒绝,场面一度十分尴尬。
有个公式可以参考:
连接池大小 = (核心数 * 2) + 有效磁盘 spindles 数量
啥意思?如果你机器是8核,SSD,连接池大小设成17左右就差不多了。别tm一股脑设成100,然后跟我抱怨"MySQL太慢了"。
最小空闲连接数(minimumIdle):这个设太高浪费资源,设太低每次突发请求都要重新建立连接,延迟爆炸。建议设成最大连接数的30%-50%,给突发留点buffer。
连接最大存活时间(maxLifetime):MySQL的wait_timeout默认是8小时,但你连接池设的maxLifetime是30分钟。这就是个博弈——设太短频繁重建,设太长可能遇到MySQL端连接已断但池里还存着的诡异问题。
最佳实践:maxLifetime比MySQL的wait_timeout少个1-2分钟,留点余量。
timeout这个参数,才是真正的幕后黑手
来,说说connectionTimeout。你知道HikariCP的默认connectionTimeout是多少吗?
30秒。
30秒啊朋友们。想象一下这个场景:你的MySQL因为某个慢查询开始堵塞,新请求过来要连接,池里没空位,开始等。等30秒,抛出异常,用户看到的是"服务不可用"。
但实际上呢?如果你把connectionTimeout设成5秒,监控系统早就报警了,你可以在雪崩之前介入,而不是等用户已经开始骂娘了才知道出事。
timeout不是越短越好,而是要足够短,让问题早点暴露。等30秒才发现问题,黄花菜都凉了。
实战调参指南
上代码,这是我在生产环境验证过的一套配置(8核16G机器,MySQL 8.0):
spring:
datasource:
hikari:
maximum-pool-size: 20
minimum-idle: 8
connection-timeout: 5000
idle-timeout: 300000
max-lifetime: 1760000
connection-test-query: SELECT 1
解释一下:
- maximum-pool-size: 20,不贪多,够用就行
- minimum-idle: 8,保留足够的热连接
- connection-timeout: 5000(5秒),5秒还拿不到连接就报警
- idle-timeout: 5分钟,空闲连接5分钟后释放
- max-lifetime: 1760000ms(约29分钟),比MySQL的wait_timeout(8小时)少很多
这套配置跑下来,QPS稳定在2000左右,CPU利用率60%上下,没出过连接池问题。
监控才是大哥
配完了就完事了?图样。
连接池不监控,等于裸奔。HikariCP自带JMX监控,但你得接入Prometheus+Grafana才能真正用起来。
这几个指标必须看:
Active Connections:当前活跃连接数。如果长期接近maximum-pool-size,说明你池子小了,要么扩容要么优化慢查询。
Idle Connections:空闲连接数。如果长期为0,说明最小空闲连接数设小了,突发请求全靠新建连接,延迟高。
Wait Threads:等待连接的线程数。这个大于0就该报警了,意味着连接不够用,请求在排队。
Connection Timeout:连接超时次数。如果这个数字在涨,说明MySQL响应慢了,或者连接池真不够用了。
最后说几句
数据库连接池这玩意儿,入门门槛低,但玩好不容易。默认配置不是不能用,是你得知道它为什么那样设,以及在什么场景下要改。
最怕的就是那种"我以为设大了就稳了"的选手,最后设了个500连接的池子,MySQL最大连接数默认151,整整三层楼的差距。
记住:连接池是用来保护你的服务的,不是用来试探MySQL极限的。合理配置 + 认真监控,才是让服务稳如老狗的正确姿势。
下次面试再问你timeout,别愣着了。