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

Quarkus原生镜像模式下AgroalDataSource连ClickHouse遇SQLException

问题:Quarkus原生镜像运行ClickHouse连接时出现SQLException错误

错误日志

redis-client, resteasy, resteasy-jackson, smallrye-context-propagation, smallrye-health, smallrye-reactive-messaging, smallrye-reactive-messaging-kafka, vertx]
23:46:46 WARN  traceId=, parentId=, spanId=, sampled= [io.ag.pool] (agroal-11) Datasource '<default>': Failed to get service com.clickhouse.client.ClickHouseSslContextProvider, server ClickHouseNode [uri=https hidden url]@-1477137086
java.sql.SQLException: Failed to get service com.clickhouse.client.ClickHouseSslContextProvider, server ClickHouseNode [uri=https hidden url]@-1477137086
    at com.clickhouse.jdbc.SqlExceptionUtils.handle(SqlExceptionUtils.java:85)
    at com.clickhouse.jdbc.SqlExceptionUtils.create(SqlExceptionUtils.java:31)
    at com.clickhouse.jdbc.SqlExceptionUtils.handle(SqlExceptionUtils.java:90)
    at com.clickhouse.jdbc.internal.ClickHouseConnectionImpl.getServerInfo(ClickHouseConnectionImpl.java:93)
    at com.clickhouse.jdbc.internal.ClickHouseConnectionImpl.<init>(ClickHouseConnectionImpl.java:298)
    at com.clickhouse.jdbc.internal.ClickHouseConnectionImpl.<init>(ClickHouseConnectionImpl.java:241)
    at com.clickhouse.jdbc.ClickHouseDriver.connect(ClickHouseDriver.java:145)
    at com.clickhouse.jdbc.ClickHouseDriver.connect(ClickHouseDriver.java:41)
    at io.agroal.pool.ConnectionFactory.createConnection(ConnectionFactory.java:226)
    at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:536)
    at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:517)
    at java.base@17.0.8/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at io.agroal.pool.util.PriorityScheduledExecutor.beforeExecute(PriorityScheduledExecutor.java:75)
    at java.base@17.0.8/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
    at java.base@17.0.8/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base@17.0.8/java.lang.Thread.run(Thread.java:833)
    at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:775)
    at org.graalvm.nativeimage.builder/com.oracle.svm.core.windows.WindowsPlatformThreads.osThreadStartRoutine(WindowsPlatformThreads.java:178)

相关代码片段

import io.agroal.api.AgroalDataSource;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@Path("")
public class ExampleRessource {
    @Inject
    AgroalDataSource dataSource;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getTime() {
        String toReturn=null;
        try (Connection con = dataSource.getConnection();
             PreparedStatement ps = con.prepareStatement("SELECT name FROM system.databases")) {
            try (ResultSet rs = ps.executeQuery();) {
                rs.next();
                toReturn = "Current time: " + rs.getString(1);
                System.out.println(toReturn);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return toReturn;
    }
}

POM配置

<properties>
    <maven.compiler.release>17</maven.compiler.release>
    <compiler-plugin.version>3.11.0</compiler-plugin.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
    <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
    <quarkus.platform.version>3.2.2.Final</quarkus.platform.version>
    <jdbc.clickhouse.version>3.0.1</jdbc.clickhouse.version>
    <surefire-plugin.version>3.0.0-M7</surefire-plugin.version>
    <clickhouse.jdbc.version>0.4.1</clickhouse.jdbc.version>
</properties>

<dependencies>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-arc</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-config-yaml</artifactId>
    </dependency>

    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-resteasy-jackson</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkiverse.jdbc</groupId>
        <artifactId>quarkus-jdbc-clickhouse</artifactId>
        <version>${jdbc.clickhouse.version}</version>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-agroal</artifactId>
    </dependency>

   <dependency>
        <groupId>com.clickhouse</groupId>
        <artifactId>clickhouse-jdbc</artifactId>
        <classifier>http</classifier>
        <version>${clickhouse.jdbc.version}</version>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>*</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>${quarkus.platform.group-id}</groupId>
            <artifactId>${quarkus.platform.artifact-id}</artifactId>
            <version>${quarkus.platform.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

已尝试操作

  • 应用正常启动运行无问题
  • 原生镜像可正常生成
  • 仅运行原生镜像时出现错误

补充信息

  • 使用GraalVM 22.3.0构建原生镜像
  • 尝试过新版本GraalVM和Quarkus,问题依旧
  • 通过URL添加?ssl=true以HTTPS方式访问ClickHouse

解决方案

错误根源是GraalVM原生镜像静态分析时,无法自动发现ClickHouse的SSL上下文提供者(com.clickhouse.client.ClickHouseSslContextProvider),该类通过ServiceLoader动态加载,默认不会被包含进原生镜像。

1. 调整依赖范围

将clickhouse-jdbc的test scope改为compile,确保生产环境能获取到SSL相关实现:

<dependency>
    <groupId>com.clickhouse</groupId>
    <artifactId>clickhouse-jdbc</artifactId>
    <classifier>http</classifier>
    <version>${clickhouse.jdbc.version}</version>
    <exclusions>
        <exclusion>
            <groupId>*</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

2. 注册反射类

使用Quarkus的@RegisterForReflection注解,在项目中添加一个配置类,将SSL上下文提供者注册到反射列表:

import io.quarkus.runtime.annotations.RegisterForReflection;

@RegisterForReflection(targets = com.clickhouse.client.core.DefaultClickHouseSslContextProvider.class)
public class NativeImageReflectionConfig {}

或者通过配置文件方式,创建src/main/resources/META-INF/native-image/reflect-config.json:

[
  {
    "name": "com.clickhouse.client.core.DefaultClickHouseSslContextProvider",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true
  }
]

3. 完善JDBC URL配置

如果是测试环境,可添加sslmode=none跳过证书验证;生产环境需配置合法证书:

quarkus.datasource.jdbc.url=jdbc:clickhouse://your-host:8443/default?ssl=true&sslmode=none

4. 重新构建原生镜像

执行命令重新构建并运行:

./mvnw clean package -Dnative
./target/your-app-name-1.0.0-SNAPSHOT-runner

内容的提问来源于stack exchange,提问作者fares ben

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 08:51:08