详解连接池参数设置(边调边看)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
性能测试 PTS,5000VUM额度
简介: 详解连接池参数设置(边调边看)

你有同感吗?

当大家在开发服务端代码的时候,会不会经常有如下疑问?

  • 纳闷 MySQL 连接池到底有多少连接?
  • 每个连接的生命周期持续多久?
  • 连接异常断开的时候到底是服务端主动断的,还是客户端主动断的?
  • 当长时间没有请求的时候,底层库是否有 KeepAlive 请求?

复杂网络情况的处理从来都是后端开发的重点和难点之一,你是不是也为各种网络情况的调试而头顶发凉呢?

所以我写了 tproxy

当我在做后端开发和写 go-zero 的时候,经常会需要监控网络连接,分析请求内容。比如:

  • 分析 gRPC 连接何时连接、何时重连,并据此调整各种参数,比如:MaxConnectionIdle
  • 分析 MySQL 连接池,当前多少连接,连接的生命周期是什么策略
  • 也可以用来观察和分析任何 TCP 连接,看服务端主动断,还是客户端主动断等等

tproxy 的安装

$ GOPROXY=https://goproxy.cn/,direct go install github.com/kevwan/tproxy@latest

或者使用 docker 镜像:

$ docker run --rm -it -p <listen-port>:<listen-port> -p <remote-port>:<remote-port> kevinwan/tproxy:v1 tproxy -l 0.0.0.0 -p <listen-port> -r host.docker.internal:<remote-port>

arm64 系统:

$ docker run --rm -it -p <listen-port>:<listen-port> -p <remote-port>:<remote-port> kevinwan/tproxy:v1-arm64 tproxy -l 0.0.0.0 -p <listen-port> -r host.docker.internal:<remote-port>

tproxy 的用法

$ tproxy --help
Usage of tproxy:
  -d duration
            the delay to relay packets
  -l string
            Local address to listen on (default "localhost")
  -p int
            Local port to listen on
  -q        Quiet mode, only prints connection open/close and stats, default false
  -r string
            Remote address (host:port) to connect
  -t string
            The type of protocol, currently support grpc

分析 gRPC 连接

tproxy -p 8088 -r localhost:8081 -t grpc -d 100ms
  • 侦听在 localhost 和 8088 端口
  • 重定向请求到 localhost:8081
  • 识别数据包格式为 gRPC
  • 数据包延迟100毫秒

img

其中我们可以看到 gRPC 的一个请求的初始化和来回,可以看到第一个请求其中的 stream id 为 1。

再比如 gRPC 有个 MaxConnectionIdle 参数,用来设置 idle 多久该连接会被关闭,我们可以直接观察到时间到了之后服务端会发送一个 http2 的 GoAway 包。

img

比如我把 MaxConnectioinIdle 设为 5 分钟,连接成功之后 5 分钟没有请求,连接就被自动关闭了,然后重新建了一个连接上来。

分析 MySQL 连接

我们来分析一下 MySQL 连接池设置对连接池的影响,比如我把参数设为:

maxIdleConns = 3
maxOpenConns = 8
maxLifetime  = time.Minute
...
conn.SetMaxIdleConns(maxIdleConns)
conn.SetMaxOpenConns(maxOpenConns)
conn.SetConnMaxLifetime(maxLifetime)

我们把 MaxIdleConns 和 MaxOpenConns 设为不同值,然后我们用 hey 来做个压测:

hey -c 10 -z 10s "http://localhost:8888/lookup?url=go-zero.dev"

我们做了并发为10QPS且持续10秒钟的压测,连接结果如下图:

img

我们可以看到:

  • 10秒钟内建立了2000+的连接
  • 过程中在不停的关闭已有连接,重开新的连接
  • 每次连接使用完放回去,可能超过 MaxIdleConns 了,然后这个连接就会被关闭
  • 接着来新请求去拿连接时,发现连接数小于 MaxOpenConns,但是没有可用请求了,所以就又新建了连接

这也就是我们经常会看到 MySQL 很多 TIME_WAIT 的原因。

然后我们把 MaxIdleConns 和 MaxOpenConns 设为相同值,然后再来做一次相同的压测:

img

我们可以看到:

  • 一直维持着8个连接不变
  • 压测完过了一分钟(ConnMaxLifetime),所有连接被关闭了

这里的 ConnMaxLifetime 一定要设置的小于 wait_timeout,可以通过如下方式查看 wait_timeout 值:

img

我建议设置小于5分钟的值,因为有些交换机会5分钟清理一下空闲连接,比如我们在做社交的时候,一般心跳包不会超过5分钟。具体原因可以看

https://github.com/zeromicro/go-zero/blob/master/core/stores/sqlx/sqlmanager.go#L65

其中 go-sql-driver 的 issue 257 里有一段也在说 ConnMaxLifetime,如下:

14400 sec is too long. One minutes is enough for most use cases.

Even if you configure entire your DC (OS, switch, router, etc...), TCP connection may be lost from various reasons. (bug in router firmware, unstable power voltage, electric nose, etc...)

所以如果你不知道 MySQL 连接池参数怎么设置,可以参考 go-zero 的设置。

另外,ConnMaxIdleTime 对上述压测结果没有影响,其实你也不需要设置它。

如果你对上述设置有疑问,或者觉得哪里有误,欢迎在 go-zero 群里一起讨论。

项目地址

tproxy: https://github.com/kevwan/tproxy

go-zero: https://github.com/zeromicro/go-zero

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3月前
|
SQL druid Java
线程池相关故障问题之Druid数据库连接池中,为何需要设置TransactionTimeout
线程池相关故障问题之Druid数据库连接池中,为何需要设置TransactionTimeout
104 0
|
SQL Java 数据库连接
自定义HikariCP连接池
自定义HikariCP连接池
489 0
|
SQL 缓存 关系型数据库
连接池设置
连接池设置
102 0
|
监控 Java 数据库连接
c3p0连接池
c3p0连接池
134 0
|
关系型数据库 数据库连接 数据库
数据库连接数配置
数据库连接数配置
609 0
数据库连接数配置
|
Java 数据库连接 API
自定义数据库连接池
自定义数据库连接池
108 0
自定义数据库连接池
连接池问题
连接池问题
166 0
|
存储 缓存 固态存储
数据库连接池大小设置,你学会了吗
数据库连接池大小设置,你学会了吗
751 0
|
网络协议 Dubbo Oracle
数据库连接池设置多少连接才合适?
前段时间在一个老项目中经历过一个问题:一个 Dubbo 服务,启动的时候慢的要死,后来看日志查原因整个过程一直在初始化数据库连接。一看数据库连接参数,连接池大小:1024。 很多入行晚的同学没有经历过手写 JDBC 连接的日子。那个时候没有数据库连接池的概念,都是原生代码一顿搞,后来有了 iBATIS 之后 Java 开发的繁杂程度才逐渐减轻,也衍生 C3P0 数据库连接池这种基础的东西。
2729 0
数据库连接池设置多少连接才合适?
|
XML SQL Java
c3p0连接池的用法
使用DButils进行连接并对数据库进行操作
1039 1
c3p0连接池的用法