You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ClickHouse Java客户端复用实例插入10次后遇执行超时问题求助

问题分析

你遇到的10条数据插入成功后第11条超时的问题,核心原因是Apache HttpClient5的默认连接池最大连接数为10:当循环发起第11次请求时,连接池已无可用连接,等待超时后抛出Code:159异常。同时你当前的单条插入方式会频繁占用连接,进一步加剧了连接池耗尽的问题。

解决方案

1. 配置HttpClient连接池实现连接复用

手动配置HttpClient5的连接池参数,传递给ClickHouseClient,控制连接的最大数量、空闲回收规则,避免连接耗尽。

调整后的Java代码如下:

import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.util.TimeValue;
import org.apache.hc.core5.util.Timeout;

import java.util.HashMap;
import java.util.UUID;

public class ClickHouseBatchInsert {
    public static void main(String[] args) {
        // 配置连接池
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
        // 设置总最大连接数
        connManager.setMaxTotal(50);
        // 设置单路由最大连接数
        connManager.setDefaultMaxPerRoute(20);
        // 空闲连接自动回收超时
        connManager.setValidateAfterInactivity(TimeValue.ofSeconds(30));

        // 配置Socket参数
        SocketConfig socketConfig = SocketConfig.custom()
                .setSoTimeout(Timeout.ofSeconds(10))
                .setSoKeepAlive(true)
                .build();
        connManager.setDefaultSocketConfig(socketConfig);

        // 构建带连接池的HttpClient
        CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(connManager)
                .build();

        // 配置ClickHouse客户端
        HashMap<String, String> options = new HashMap<>();
        options.put("user", "user");
        options.put("password", "pass");
        ClickHouseNode server = ClickHouseNode.of("my-clickhouse-host", options);

        // 复用ClickHouseClient实例
        try (ClickHouseClient client = ClickHouseClient.builder()
                .nodeSelector(ClickHouseNodeSelector.of(ClickHouseProtocol.HTTP))
                .httpClient(httpClient)
                .build()) {

            // 批量插入:合并所有数据为一个请求
            StringBuilder batchSql = new StringBuilder("INSERT INTO mytable VALUES ");
            for (int i = 0; i < 11; i++) {
                String id = UUID.randomUUID().toString();
                String field1 = "field1" + i;
                String field2 = "field2" + i;
                String field3 = "field3" + i;
                String field4 = "field4" + i;

                if (i > 0) {
                    batchSql.append(", ");
                }
                batchSql.append(String.format("('%s', '%s', '%s', '%s', '%s')",
                        id, field1, field2, field3, field4));
            }

            // 执行批量插入
            client.read(server)
                    .write()
                    .format(ClickHouseFormat.CustomSeparated)
                    .query(batchSql.toString())
                    .executeAndWait();

            System.out.println("11条数据全部插入成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. 关键优化点说明

  • 连接池配置:通过PoolingHttpClientConnectionManager自定义连接数上限,避免默认10个连接的限制;同时配置空闲连接自动回收,防止连接泄漏。
  • 复用ClickHouseClient:通过try-with-resources管理Client生命周期,确保资源合理释放;注入自定义HttpClient后,所有请求都会复用连接池中的连接。
  • 批量插入:将多条INSERT合并为一个请求,大幅减少连接占用次数,既提升插入效率,又从根源上避免连接池被频繁请求占满。

额外安全优化:避免SQL注入

当前代码用字符串拼接SQL存在注入风险,建议使用参数化批量插入:

try (ClickHouseClient client = ClickHouseClient.builder().httpClient(httpClient).build();
     ClickHouseSession session = client.connect(server).get()) {
    String insertSql = "INSERT INTO mytable VALUES (?, ?, ?, ?, ?)";
    try (ClickHouseStatement stmt = session.createStatement()) {
        for (int i = 0; i < 11; i++) {
            stmt.setObject(1, UUID.randomUUID().toString());
            stmt.setObject(2, "field1" + i);
            stmt.setObject(3, "field2" + i);
            stmt.setObject(4, "field3" + i);
            stmt.setObject(5, "field4" + i);
            stmt.addBatch();
        }
        stmt.executeBatch();
    }
}

这种方式既避免了语法错误,又提升了请求安全性。

内容的提问来源于stack exchange,提问作者Octavio Cunha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 20:03:18