当前位置: 首页 > 知识库问答 >
问题:

Quarkus的SQL连接耗尽,Hibernate反应式花招

曹建明
2023-03-14

我有一个Quarkus应用程序,它使用hibernate-reactive-panache运行一些查询,然后处理结果并通过Rest调用返回JSON。对于每个Rest调用,执行5 DB查询,最后一个查询将加载大约20k行:

    public Uni<GraphProcessor> loadData(GraphProcessor graphProcessor){
    return myEntityRepository.findByDateLeaving(graphProcessor.getSearchDate())
            .select().where(graphProcessor::filter)
            .onItem().invoke(graphProcessor::onNextRow).collect().asList()
            .onItem().invoke(g -> log.info("loadData - end"))
            .replaceWith(graphProcessor);
}

//In myEntityRepository
public Multi<MyEntity> findByDateLeaving(LocalDate searchDate){
    LocalDateTime startDate = searchDate.atStartOfDay();
    return MyEntity.find("#MyEntity.findByDate",
            Parameters.with("startDate", startDate)
                    .map()).stream();

}

前4次都很好,但第5次我接到电话

 11:12:48:070 ERROR [org.hibernate.reactive.util.impl.CompletionStages:121] (147) HR000057: Failed to execute statement [$1select <ONE OF THE QUERIES HERE>]: $2could not load an entity: [com.mycode.SomeEntity#1]: java.util.concurrent.CompletionException: io.vertx.core.impl.NoStackTraceThrowable: Timeout
    at <16 internal lines>
io.vertx.sqlclient.impl.pool.SqlConnectionPool$1PoolRequest.lambda$null$0(SqlConnectionPool.java:202) <4 internal lines>
    at io.vertx.sqlclient.impl.pool.SqlConnectionPool$1PoolRequest.lambda$onEnqueue$1(SqlConnectionPool.java:199) <15 internal lines>
Caused by: io.vertx.core.impl.NoStackTraceThrowable: Timeout

我检查了https://quar kus . io/guides/reactive-SQL-clients # pooled-connection-idle-time out并配置了quar kus . data source . reactive . idle-time out = 1000

这本身并没有什么不同。我增加了quarkus.datasource.reactive.max-大小=10

在再次超时之前,我能够运行10个Rest调用。在max-size=20的池设置下,我能够运行它20次。所以看起来每个Rest调用都会用完一个SQL连接,并且不会再次释放它。

是否需要执行某些操作才能手动释放连接,或者这仅仅是一个错误?

共有1个答案

唐利
2023-03-14

问题是在反应性Rest方法上使用@Blocking。更多信息见https://github.com/quarkusio/quarkus/issues/25138和https://quarkus.io/blog/resteasy-reactive-smart-dispatch/。

因此,如果您有一个返回Uni或Multi的rest方法,不要在调用中使用@Blocking。我不得不最初添加它,因为我收到一个异常,告诉我线程不能阻塞。这是由于一些CPU密集型计算。添加@Blocking使该异常消失(在开发模式下,但是在本机模式下出现了另一个问题),但是导致了这个SQL池问题。

真正的解决方案是使用emitOn来改变cpu密集型方法的线程:

 .emitOn(Infrastructure.getDefaultWorkerPool())
 .onItem().transform(processor::cpuIntensiveMethod)
 类似资料:
  • 我在项目中使用ApacheTomcat JDBC连接池。我很困惑,因为在重负下,我一直看到以下错误: 我的期望是,使用池,新连接的请求将被保留在队列中,直到连接可用。相反,当池达到容量时,请求似乎会被拒绝。这种行为可以改变吗? 谢谢, 达尔 这是我的池配置:

  • 我有使用hikari池创建连接池的Spring启动应用程序。我们正在使用postgres sql用于db。当我以低qps命中系统时,请求需要大约200毫秒来执行。当部署一个pod并且qps为15时,事情保持良好状态。但是一旦我将qps增加到20,请求就开始需要大约10秒来处理,连接池变空(java.sql.SQLTransientConntion异常:菲尼克斯-连接不可用,请求在30183毫秒后超

  • 我有一个Spring启动,Hibernate使用java应用程序。我部署它在一个jetty webserver与多个实例.如果我有太多(大于10)很多实例我得到 许多连接(10x实例)显示为空闲 ps: 实例的Hikari跟踪日志: 设置 没有记录任何有趣的事情。我认为这看起来很有趣-连接不可用 有什么办法可以调试这个吗?我也在java 7上,所以hikari 2.4.7

  • 我在应用程序中使用连接池(snaq.db.ConnectionPool)。连接池的初始化方式如下: 使用的DB池值是: 我的应用程序在某处泄漏连接(连接未被释放),因此连接池已耗尽。我现在已经修好了密码。 空闲超时后连接不应该关闭吗?如果这不是正确的假设,有没有办法关闭打开的空闲连接(仅通过java代码)?

  • 在为了使用多线程而修改了一个服务方法之后,我发现如果不止一个用户多次尝试请求页面(并调用服务方法),服务器就会抛出“无法连接,池耗尽”异常。让我提供一个我的服务类的例子。 我已经在这个问题上挣扎了一个多星期,我找不到解决方案。我不太明白Grails如何与会话、连接和事务一起工作。我的猜测是跟随。当调用ConvertDocumentToJSON时,它从池中获取连接(4个用户,每个用户25个线程=10

  • 问题内容: 我在GlassFish上有一个Java-JSF Web应用程序,我想在其中使用连接池。因此,我创建了一个有范围的Bean,可与其他Bean的实例一起使用: 这样,连接池很快就会被填满。在“ db-related”视图中进行几次导航后,应用程序将停止以下操作: RAR5117:无法从连接池[mysql_testPool]获取/创建连接。原因:使用中的连接等于最大池大小和已过期的最大等待时