连接池 ExclusiveDBConnectionPool

Java API 提供 ExclusiveDBConnectionPool 连接池用以执行任务。每个 worker 独占一个 DBConnection,用户可以通过 execute 方法提交任务,然后使用 BasicDBTaskgetResult 方法获取任务执行结果。

自 Java API 3.00.5.2 版本起,ExclusiveDBConnectionPool 新增 minimumPoolSizemaximumPoolSizeidleTimeout 参数,支持按任务压力动态扩容,并在空闲后回收到最小连接数。为保证兼容性,已有构造方法和已有 public 方法签名保持不变。

使用说明

ExclusiveDBConnectionPool 支持两种使用模式:

  • 固定连接数模式:使用已有构造方法,通过 count 指定连接数。
  • 弹性连接池模式:自 Java API 3.00.5.2 版本起提供,使用新增构造方法或 ExclusiveDBConnectionPoolConfig,通过 minimumPoolSizemaximumPoolSizeidleTimeout 控制连接池容量。

固定连接数模式

已有构造方法保持不变:

public ExclusiveDBConnectionPool(
    String host,
    int port,
    String uid,
    String pwd,
    int count,
    boolean loadBalance,
    boolean enableHighAvailability
) throws IOException
public ExclusiveDBConnectionPool(
    String host,
    int port,
    String uid,
    String pwd,
    int count,
    boolean loadBalance,
    boolean enableHighAvailability,
    String[] highAvailabilitySites,
    String initialScript,
    boolean compress,
    boolean useSSL,
    boolean usePython
) throws IOException

参数介绍:

host String 类型,表示主机名。

port int 类型,表示端口。

uid String 类型,可选参数,表示登录的用户名,默认值为空。

pwd String 类型,可选参数,表示登录的密码,默认值为空。

count 正整数,表示固定连接数模式下连接池中的连接数量。当提交的任务数量大于连接数时,部分任务会等待,直到出现空闲连接后再执行。

loadBalance boolean 类型,表示初始化连接时是否开启负载均衡。

enableHighAvailability boolean 类型,可选参数,表示是否针对连接池中的连接开启高可用,默认值为 false。

highAvailabilitySites String 数组类型,可选参数,表示所有可用节点的地址和端口,格式为 ip:port。须开启 enableHighAvailability 后才可使用,默认为 null。

initialScript String 类型,可选参数,表示初始化脚本,默认为空。

compress boolean 类型,可选参数,表示是否在下载时压缩数据,默认值为 false。

useSSL boolean 类型,可选参数,表示是否使用 SSL 连接,默认值为 false。若要开启 SSL 连接,服务器端配置文件须同时配置 enableHTTPS=true

usePython boolean 类型,可选参数,表示是否开启 Python 解析,默认值为 false。

兼容性说明:

  • 自 Java API 3.00.5.2 版本起,已有构造方法中的 count 在内部映射为 minimumPoolSize,同时设置 maximumPoolSize = count,因此仍保持固定连接数行为。使用已有构造方法时,不会触发动态扩容,也不会触发 idleTimeout 空闲回收。

弹性连接池模式

自 Java API 3.00.5.2 版本起,新增以下构造方法:

public ExclusiveDBConnectionPool(
    String host,
    int port,
    String uid,
    String pwd,
    int minimumPoolSize,
    int maximumPoolSize,
    int idleTimeout,
    boolean loadBalance,
    boolean enableHighAvailability
) throws IOException
public ExclusiveDBConnectionPool(
    String host,
    int port,
    String uid,
    String pwd,
    int minimumPoolSize,
    int maximumPoolSize,
    int idleTimeout,
    boolean loadBalance,
    boolean enableHighAvailability,
    String[] highAvailabilitySites,
    String initialScript,
    boolean compress,
    boolean useSSL,
    boolean usePython
) throws IOException

新增参数介绍:

minimumPoolSize 正整数,表示连接池初始化时创建的最小 worker/连接数。空闲回收不会使当前连接数低于该值。默认值为 5;若设置值小于等于 0,则使用默认值 5。

maximumPoolSize 正整数,表示连接池允许扩容到的最大 worker/连接数。默认值为 5;若设置值小于等于 0,则使用默认值 5;若小于 minimumPoolSize,则会被设置为 minimumPoolSize

idleTimeout int 类型,表示超过 minimumPoolSize 的 worker 保持空闲状态的最长时间,单位为毫秒。超过该时间后,worker 会退出并关闭其独占的 DBConnection。默认值为 600000,即 10 分钟;最小有效值为 10000,即 10 秒;若设置值小于 10000,则使用默认值 600000。

使用 ExclusiveDBConnectionPoolConfig

自 Java API 3.00.5.2 版本起,新增 ExclusiveDBConnectionPoolConfig 配置类,用于承载连接参数和弹性连接池参数。

public ExclusiveDBConnectionPool(ExclusiveDBConnectionPoolConfig config) throws IOException

ExclusiveDBConnectionPoolConfig 仅可通过 setXxx 方法配置参数,示例如下:

ExclusiveDBConnectionPoolConfig config = new ExclusiveDBConnectionPoolConfig();
config.setHostName(HOST);
config.setPort(PORT);
config.setUserId(USER);
config.setPassword(PASSWORD);
config.setMinimumPoolSize(1);
config.setMaximumPoolSize(3);
config.setIdleTimeout(10000);
config.setLoadBalance(false);
config.setEnableHighAvailability(false);

ExclusiveDBConnectionPool pool = new ExclusiveDBConnectionPool(config);

ExclusiveDBConnectionPoolConfig 支持的参数如下:

hostName String 类型,表示主机名,默认值为 localhost。

port int 类型,表示端口,默认值为 8848。

userId String 类型,表示登录的用户名,默认值为空。

password String 类型,表示登录的密码,默认值为空。

minimumPoolSize 正整数,表示连接池中最小 worker/连接数,默认值为 5。

maximumPoolSize 正整数,表示连接池中允许同时存在的最大 worker/连接数,默认值为 5。

idleTimeout int 类型,表示超过 minimumPoolSize 的 worker 可保持空闲状态的最长时间,单位为毫秒,默认值为 600000。

initialScript String 类型,表示初始化脚本,默认为空。

compress boolean 类型,表示是否在下载时压缩数据,默认值为 false。

useSSL boolean 类型,表示是否使用 SSL 连接,默认值为 false。

usePython boolean 类型,表示是否开启 Python 解析,默认值为 false。

loadBalance boolean 类型,表示是否开启负载均衡,默认值为 false。

enableHighAvailability boolean 类型,表示是否开启高可用,默认值为 false。

highAvailabilitySites String 数组类型,表示开启高可用情况下指定的主机名和端口号数组,默认为 null。

新旧参数映射关系

自 Java API 3.00.5.2 版本起,count 与新增参数的关系如下:

使用入口minimumPoolSizemaximumPoolSizeidleTimeout最终行为
已有构造方法,传入 countcountcount不生效固定 count 个连接,不动态扩容,也不动态缩容。
新增构造方法用户设置的 minimumPoolSize用户设置并校验后的 maximumPoolSize对超过 minimumPoolSize 的空闲 worker 生效初始化为最小连接数,任务压力上升时最多扩容到最大连接数,空闲后回收到最小连接数。
ExclusiveDBConnectionPoolConfig用户设置或默认值用户设置或默认值,并保证不小于 minimumPoolSize用户设置或默认值初始化为最小连接数,任务压力上升时最多扩容到最大连接数,空闲后回收到最小连接数。

注意:已有构造方法中的 count 对外含义不变,仍表示固定连接数。它不会因为新增了 minimumPoolSizemaximumPoolSizeidleTimeout 而自动变成弹性连接池。

示例

以下示例假定 HOSTPORTUSERPASSWORDHA_SITES 已通过环境变量或配置文件定义。

以下示例创建一个固定大小为 5 的连接池,开启负载均衡和高可用,指定高可用节点,开启压缩,使用 SSL 连接,不使用 Python 解析。

public void demoExclusiveDBConnectionPool() throws IOException {
    DBConnectionPool pool = new ExclusiveDBConnectionPool(
        HOST,
        PORT,
        USER,
        PASSWORD,
        5,
        true,
        true,
        HA_SITES,
        "",
        true,
        true,
        false
    );
}

该用法在 Java API 3.00.5.2 版本起仍保持固定连接数行为,初始化后连接数为 5,后续不会动态扩容或空闲回收。

以下示例创建一个弹性连接池,初始化 1 个连接,任务压力增加时最多扩容到 3 个连接。超过最小连接数的 worker 空闲 10 秒后会自动退出并关闭其独占连接。

public void demoDynamicExclusiveDBConnectionPool() throws IOException {
    ExclusiveDBConnectionPool pool = new ExclusiveDBConnectionPool(
        HOST,
        PORT,
        USER,
        PASSWORD,
        1,
        3,
        10000,
        false,
        false
    );

    List<DBTask> tasks = new ArrayList<>();
    tasks.add(new BasicDBTask("sleep(1000); 1"));
    tasks.add(new BasicDBTask("sleep(1000); 1"));
    tasks.add(new BasicDBTask("sleep(1000); 1"));

    pool.execute(tasks);
    pool.shutdown();
}
public void demoExclusiveDBConnectionPoolConfig() throws IOException {
    ExclusiveDBConnectionPoolConfig config = new ExclusiveDBConnectionPoolConfig();
    config.setHostName(HOST);
    config.setPort(PORT);
    config.setUserId(USER);
    config.setPassword(PASSWORD);
    config.setMinimumPoolSize(1);
    config.setMaximumPoolSize(3);
    config.setIdleTimeout(10000);
    config.setLoadBalance(false);
    config.setEnableHighAvailability(false);

    ExclusiveDBConnectionPool pool = new ExclusiveDBConnectionPool(config);
    DBTask task = new BasicDBTask("1 + 1");
    pool.execute(task);

    System.out.println(task.getResult());
    pool.shutdown();
}

方法介绍

ExclusiveDBConnectionPool 支持的方法如下表:

说明:getCurrentConnectionCount()getMinimumPoolSize()getMaximumPoolSize()getIdleTimeout()getActiveConnectionsCount()getIdleConnectionsCount()ExclusiveDBConnectionPool 具体类上的新增方法,未新增到 DBConnectionPool 接口中。若需要调用这些方法,请使用 ExclusiveDBConnectionPool 类型声明连接池对象。

方法名详情
ExclusiveDBConnectionPool(String host, int port, String uid, String pwd, int count, boolean loadBalance, boolean enableHighAvailability)构造方法,创建固定连接数模式连接池。
ExclusiveDBConnectionPool(String host, int port, String uid, String pwd, int count, boolean loadBalance, boolean enableHighAvailability, String[] highAvailabilitySites, String initialScript, boolean compress, boolean useSSL, boolean usePython)构造方法,创建固定连接数模式连接池,并支持高可用节点、初始化脚本、压缩、SSL、Python 解析等参数。
ExclusiveDBConnectionPool(String host, int port, String uid, String pwd, int minimumPoolSize, int maximumPoolSize, int idleTimeout, boolean loadBalance, boolean enableHighAvailability)自 Java API 3.00.5.2 版本起新增。构造方法,创建弹性连接池。
ExclusiveDBConnectionPool(String host, int port, String uid, String pwd, int minimumPoolSize, int maximumPoolSize, int idleTimeout, boolean loadBalance, boolean enableHighAvailability, String[] highAvailabilitySites, String initialScript, boolean compress, boolean useSSL, boolean usePython)自 Java API 3.00.5.2 版本起新增。构造方法,创建弹性连接池,并支持高可用节点、初始化脚本、压缩、SSL、Python 解析等参数。
ExclusiveDBConnectionPool(ExclusiveDBConnectionPoolConfig config)自 Java API 3.00.5.2 版本起新增。通过配置类创建弹性连接池。
execute(DBTask task)执行单个任务。
execute(DBTask task, int timeOut)执行单个任务,并设置等待超时时间,单位为毫秒。
execute(List<DBTask> tasks)执行批量任务。
waitForThreadCompletion()等待已提交任务执行完成。
getConnectionCount()获取当前实际存在的 worker/连接数。固定连接数模式下等于 count;弹性连接池模式下会在 minimumPoolSizemaximumPoolSize 之间变化。
getCurrentConnectionCount()自 Java API 3.00.5.2 版本起新增。获取当前实际存在的 worker/连接数。固定连接数模式下等于 count;弹性连接池模式下会在 minimumPoolSizemaximumPoolSize 之间变化。
getMinimumPoolSize()自 Java API 3.00.5.2 版本起新增。获取最小 worker/连接数。
getMaximumPoolSize()自 Java API 3.00.5.2 版本起新增。获取最大 worker/连接数,即弹性连接池允许扩容到的最大容量。
getIdleTimeout()自 Java API 3.00.5.2 版本起新增。获取空闲回收超时时间,单位为毫秒。
getActiveConnectionsCount()自 Java API 3.00.5.2 版本起新增。获取当前正在执行任务的 worker/连接数。排队等待执行的任务不计入该值。
getIdleConnectionsCount()自 Java API 3.00.5.2 版本起新增。获取当前已创建但未执行任务的 worker/连接数。
shutdown()关闭连接池。该方法会等待已提交任务执行完成后释放连接。若当前连接池不再使用,建议主动调用该方法及时释放连接资源。

兼容性说明:

  • getConnectionCount() 是已有方法,自 Java API 3.00.5.2 版本起其返回值仍表示当前实际存在的 worker/连接数。对于使用已有构造方法创建的固定连接数模式,该值始终等于 count;对于弹性连接池模式,该值会随扩容和空闲回收变化。如需获取配置的最大并发能力,请使用 getMaximumPoolSize()

连接池未关闭时,以下关系成立:

getActiveConnectionsCount() + getIdleConnectionsCount() = getCurrentConnectionCount()

其中,idle 表示连接当前没有执行任务,并不表示该连接一定会被回收。只有超过 minimumPoolSize 且空闲时间达到 idleTimeout 的 worker/连接才会被回收。

创建一个任务

Java API 提供 BasicDBTask 对象帮助用户创建任务。BasicDBTask 包装了需要执行的脚本、参数、执行状态和结果。

构造方法:

public BasicDBTask(String script)

参数介绍:

script String 类型,表示要执行的脚本。

示例代码:

public void demoBasicDBTask() {
    BasicDBTask task = new BasicDBTask("x=1; x;");
}

提交任务 execute

创建任务后,可以使用 execute 方法向连接池提交任务。

task DBTask 类型,表示单个任务对象。

tasks List<DBTask> 类型,表示批量任务对象。

timeOut int 类型,表示等待任务结束的超时时间,单位为毫秒。默认值为 -1,表示一直等待任务结束。

代码示例如下,执行一个简单脚本任务,并设置超时时间为 10000:

public void demoExclusiveDBConnectionPool() throws IOException {
    ExclusiveDBConnectionPool pool = new ExclusiveDBConnectionPool(
        HOST,
        PORT,
        USER,
        PASSWORD,
        5,
        false,
        false
    );

    DBTask task = new BasicDBTask("x=1; x;");
    pool.execute(task, 10000);
    pool.shutdown();
}

提交多个任务

当需要同时提交多个任务时,可以声明一个泛型为 DBTaskList,实现一次提交多个任务。

public void demoExclusiveDBConnectionPool() throws IOException {
    DBConnectionPool pool = new ExclusiveDBConnectionPool(
        HOST,
        PORT,
        USER,
        PASSWORD,
        5,
        false,
        false
    );

    List<DBTask> dbTaskList = new ArrayList<>();
    dbTaskList.add(new BasicDBTask("1 + 1"));
    dbTaskList.add(new BasicDBTask("x = 1; x;"));
    dbTaskList.add(new BasicDBTask("sum(1 2 3 NULL 4);"));

    pool.execute(dbTaskList);
    pool.shutdown();
}

获取任务的返回值

可以通过 BasicDBTask 类的以下方法获取任务执行的返回值和信息:

方法名说明
boolean isSuccessful()返回任务是否执行成功。
Entity getResult()获取任务执行结果。
String getErrorMsg()获取任务执行期间发生的异常信息。

使用示例:

public void demoExclusiveDBConnectionPool() throws IOException {
    DBConnectionPool pool = new ExclusiveDBConnectionPool(
        HOST,
        PORT,
        USER,
        PASSWORD,
        5,
        false,
        false
    );

    DBTask task = new BasicDBTask("sum(1 2 3 NULL 4);");
    pool.execute(task);

    System.out.println(task.isSuccessful());
    System.out.println(task.getResult());
    System.out.println(task.getErrorMsg());

    pool.shutdown();
}

执行结果:

true
10
null

机制介绍

使用已有构造方法创建连接池时,连接池会在初始化时创建 count 个 worker/连接。每个 worker 独占一个 DBConnection,从任务队列中获取任务并执行。

  • count 必须为正整数。
  • 初始化后连接数固定为 count
  • 不执行动态扩容。
  • 不执行 idleTimeout 空闲回收。
  • getConnectionCount() 返回值等于 count

使用新增构造方法或 ExclusiveDBConnectionPoolConfig 创建连接池时,连接池进入弹性连接池模式。

  • 初始化时创建 minimumPoolSize 个 worker/连接。
  • 提交任务时,连接池根据任务队列长度和正在执行的任务数量估算当前需要的 worker 数。
  • 如果当前 worker 数小于任务需求,且未达到 maximumPoolSize,则创建新的 worker。
  • 新 worker 创建后立即参与任务消费。
  • 超过 minimumPoolSize 的 worker 在空闲超过 idleTimeout 后自动退出,并关闭其独占的 DBConnection

ExclusiveDBConnectionPool 中每个 worker 独占一个 DBConnection。弹性连接池模式下,空闲回收的对象是超过 minimumPoolSize 的 worker 及其独占连接。

  • 当前 worker 数量大于 minimumPoolSize 时,超过 minimumPoolSize 的空闲 worker 可被回收。
  • 当前 worker 数量小于等于 minimumPoolSize 时,即使 worker 空闲时间超过 idleTimeout,也不会被回收。
  • 固定连接数模式不执行 idleTimeout 空闲回收。

loadBalance = false 时,连接池中的 worker 都连接到指定的 host:port

loadBalance = true 时:

  • 初始化阶段获取可用数据节点列表。
  • worker 按序轮询连接不同节点,使连接分布相对均衡。
  • 弹性连接池模式下,后续动态扩容创建 worker 时复用初始化阶段得到的节点列表,不会在每次扩容时重新访问 controller 获取节点列表。

enableHighAvailabilityhighAvailabilitySites 的处理逻辑保持与已有构造方法一致。

用户可通过 waitForThreadCompletion() 等待已提交任务全部完成。

用户可通过 shutdown() 关闭连接池:

pool.shutdown();

shutdown() 会先等待已提交任务完成,再中断 worker 并释放连接。弹性连接池模式下,waitForThreadCompletion() 等待的是已提交任务完成,不等待 worker 回收到 minimumPoolSize,因此不会因为空闲 worker 仍在等待 idleTimeout 而阻塞。