2.6 连接池管理

在dble中每个后端MySQL节点由 PhysicalDbInstance 表示,PhysicalDbInstance中维护了两类连接:

  1. 大部分业务使用的连接由连接池管理
  2. 独立于连接池之外的连接,这类连接主要有两类:MySQL实例的心跳连接和用于OneTimeJob的一次性任务的连接,这种连接是一次性的,用完即关,次数也比较少。

2.6.1 dble后端连接池管理

后端连接池使用 CopyOnWriteArrayList 存储该MySQL实例的全量连接,通过连接的state状态来维护连接的初始化,借出,空闲,心跳,移除状态。连接池初始化之后会维护一个evictor线程来维持连接池的扩缩容以及空闲连接的有效性。结构如下图所示:

2.6_1

2.6.1.1 连接获取

业务向连接池请求获取后端连接,会遍历连接池中的全量连接直到找到第一个空闲连接。若连接池中当时没有空闲连接,则线程会进入超时等待队列,在超时时间内未获取到连接,前端报错。

2.6.1.2 连接释放

后端连接处理完业务之后,状态会被置为空闲,并且处理线程会唤醒在超时等待队列中的线程来重新获取连接。

2.6.1.3 连接池扩缩容

连接池初始化之后会维护一个evictor线程来维持连接池的扩缩容以及空闲连接的有效性,evictor线程是一个定时任务。

扩容:当空闲连接数小于minCon时,维持连接池中的空闲连接在minCon的数量上,每次扩容的连接数量通过以下公式计算:min(配置的最小空闲连接数 - 当前连接池中空闲连接数, 配置的最大连接数 - 连接池中的总连接数) - 正在创建的连接数,若数量大于0,则创建该数量的连接。

缩容:当空闲连接数大于minCon时,维持连接池中的空闲连接在minCon的数量上,每次关闭的连接数量通过以下公式计算:(连接池中的最小连接数 - 配置的最小连接) > 0 && 连接达到 idleTimeout。

2.6.1.4 连接有效性检测

在连接的不同阶段,提供对连接有效性的检测手段。

  • testOnCreate为true,在连接被创建后,会发送ping命令探测连接有效性,若在connectionHeartbeatTimeout没有收到结果,会关闭连接。
  • testOnBorrow为true,在连接被借出后,会发送ping命令探测连接有效性,若在connectionHeartbeatTimeout没有收到结果,会关闭连接。
  • testOnReturn为true,在连接被返回后,会发送ping命令探测连接有效性,若在connectionHeartbeatTimeout没有收到结果,会关闭连接。
  • testWhileIdle为true,对所有空闲连接,发送ping命令探测连接有效性,若在connectionHeartbeatTimeout没有收到结果,会关闭连接。

2.6.2 连接状态管理

由上文我们知道,后端连接池使用 CopyOnWriteArrayList 存储该MySQL实例的全量连接,通过连接的state状态来维护连接的初始化,借出,空闲,心跳,移除状态。下面是连接状态的跃迁图:

2.6.3 连接流量控制阈值

dble对分库分表的流量有控制功能,详见2.25 dble流量控制
后端连接的高水位(flowHighLevel)和低水位(flowLowLevel)的配置也在这里体现,单位字节

2.6.4 连接池属性

属性名 默认值 单位 含义
testOnCreate false 连接创建后是否检测有效性
testOnBorrow false 连接被借出后是否检测有效性
testOnReturn false 连接被返回时是否检测有效性
testWhileIdle false 连接空闲时是否检测有效性
connectionTimeout 30000 (30s) 毫秒 获取连接的超时时间
connectionHeartbeatTimeout 20 毫秒 空闲连接检测后的超时时间
timeBetweenEvictionRunsMillis 30000 (30s) 毫秒 扩缩容线程的检测周期
idleTimeout 600000 (10 minute) 毫秒 连接空闲多久之后被回收
heartbeatPeriodMillis 10000 (10s) 毫秒 连接池的心跳周期
evictorShutdownTimeoutMillis 10000 (10s) 毫秒 扩缩容线程停止的超时时间
flowHighLevel 4194304 字节 后端连接流量控制的高水位
flowLowLevel 262144 字节 后端连接流量控制的低水位

示例:

<?xml version="1.0"?>
<!DOCTYPE dble:db SYSTEM "db.dtd">
<dble:db xmlns:dble="http://dble.cloud/">

    <dbGroup name="dbGroup1" rwSplitMode="1" delayThreshold="10000">
        <heartbeat errorRetryCount="1" timeout="10" keepAlive="60" >show slave status</heartbeat>
        <dbInstance name="instanceM1" url="ip4:3306" user="your_user" password="your_psw" maxCon="200" minCon="50" primary="true">
            <property name="testOnCreate">false</property>
            <property name="testOnBorrow">false</property>
            <property name="testOnReturn">false</property>
            <property name="testWhileIdle">true</property>
            <property name="connectionTimeout">30000</property>
            <property name="connectionHeartbeatTimeout">20</property>
            <property name="timeBetweenEvictionRunsMillis">30000</property>
            <property name="idleTimeout">600000</property>
            <property name="heartbeatPeriodMillis">10000</property>
            <property name="evictorShutdownTimeoutMillis">10000</property>
            <property name="flowHighLevel">4194304 </property>
            <property name="flowLowLevel">262144 </property>
        </dbInstance>

        <!-- can have multi read instances -->
        <dbInstance name="instanceS1" url="ip5:3306" user="your_user" password="your_psw" maxCon="200" minCon="50" primary="false">
            <property name="heartbeatPeriodMillis">60000</property>
        </dbInstance>
    </dbGroup>
</dble:db>

2.6.5 dble后端连接池的心跳管理

dble后端MySQL节点的心跳管理是通过定时任务来完成的,检测周期由heartbeatPeriodMillis来控制。dble会对每一个后端MySQL节点持有一个长连接,定期发送心跳语句,根据返回结果的不同将连接池标记为不同的状态。若心跳异常,会影响evictor线程的扩缩容。

2.6.5.1 心跳周期内的不同阶段

我们可以将每个心跳周期简单划分为两个阶段:

  • 检测阶段:心跳检测发起到收到回复的阶段
  • 空闲阶段:心跳返回后到下一个心跳检测发起的阶段

2.6.5.2 心跳状态

dble的心跳状态有四种:

  • init状态:初始状态,具体指收到第一个心跳响应报文前的状态
  • ok状态:收到一次正常的心跳返回后的状态
  • timeout状态:最近的一次心跳在HeartbeatTimeout时间段内没有收到响应
  • error状态:心跳语句返回错误或者心跳连接异常都可能导致此种状态,dble里面会有重试机制来预防网络抖动等网络方面的异常。

2.6.5.3 心跳重试

此处的心跳重试分为三种情况:第一种是心跳语句返回错误导致的重试,第二种是心跳连接关闭导致的重试,第三种是心跳超时后才收到响应导致的重试。

  • 对于心跳语句返回失败,dble会立即将连接池状态置为error状态,随即会发送errorRetryCount次心跳,若有一次心跳正常,心跳恢复成ok状态。
  • 对于心跳连接关闭引起的失败,dble会在接下来的时间立即发送errorRetryCount次心跳,若有一次心跳正常,则停止重试,但如果都失败,则将连接池状态置为error状态
  • 对于标记为timeout状态后收到姗姗来迟的OK响应, 则将会被重置为init状态并立即发送一次心跳。

2.6.6 连接池补充说明

在dble中,dble会与配置的数据库建立连接,db.xml中的dbInstance标签中配置了具体的数据库实例,dble与数据库的连接通过连接池来管理。

  • 每个dbInstance的连接池都是独立的,连接池的连接数通过dbInstance中的maxCon参数和minCon参数来控制
  • 每一个dbInstance中配置的mysql实例,dble都会建立一个连接池来管理。只有在rwSplitMode=0时,主实例会建立连接池,从实例不会建立连接池

举例:

  <dbGroup name="dbGroup1" rwSplitMode="1" delayThreshold="10000">
        <heartbeat errorRetryCount="1" timeout="10" keepAlive="60">show slave status</heartbeat>
        <dbInstance name="instanceM1" url="ip4:3306" user="your_user" password="your_psw" maxCon="200" minCon="50" primary="true">
        </dbInstance>
    </dbGroup>
     <dbGroup name="dbGroup2" rwSplitMode="1" delayThreshold="10000">
        <heartbeat errorRetryCount="1" timeout="10" keepAlive="60">show slave status</heartbeat>
        <dbInstance name="instanceM2" url="ip4:3306" user="your_user" password="your_psw" maxCon="100" minCon="10" primary="true">
        </dbInstance>
    </dbGroup>
     <dbGroup name="dbGroup3" rwSplitMode="1" delayThreshold="10000">
        <heartbeat errorRetryCount="1" timeout="10" keepAlive="60">show slave status</heartbeat>
        <dbInstance name="instanceM3" url="ip5:3306" user="your_user" password="your_psw" maxCon="200" minCon="50" primary="true">
        </dbInstance>
    </dbGroup>

配置注意事项:
1.instanceM1和instanceM2虽然配置了相同mysql,dble是根据dbInstance来建立连接池,上述例子中总共会建立三个连接池
2.instanceM1和instanceM2虽然配置了相同mysql,连接池中都是相互独立的,instanceM1的连接池中连接数量最大为200,最小为50,instanceM2的连接池中连接数量最大为100, 最小为10。二者相互独立

results matching ""

    No results matching ""