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

使用@Async@Transactional方法Spring靴

景俊拔
2023-03-14

我的springboot控制器中有@async方法,它调用service method(async)并执行一些DB事务。当这个控制器@async方法被多次调用而没有时间延迟时,它会导致org.hibernate.exception.JDBCConnectionException:无法获取JDBC连接

控制器

 @PostMapping(value = "/api/sms/sendmsgasync")
  public ResponseEntity<Boolean> sendSMSMessageAsync(@RequestBody MessageRequestDto messageRequestDto) {

    final Future<Boolean> booleanFuture = smsService.sendSingleMessageAsync(messageRequestDto, requestContext.getConversationId());
    log.debug("sendSMSMessageAsync {} <<<<", booleanFuture.isDone());
    return ResponseEntity.ok(true);
  }

服务

 @Async
  @Override
  public Future<Boolean> sendSingleMessageAsync(MessageRequestDto messageRequestDto, String convId) {


    try {
      sendSingleMessage(messageRequestDto, convId);
    }
    catch (BadRequestException | NotFoundException | TwilioException e) {
      LOG.error("Error in sendSingleMessageAsync. Error logged to SMS Gateway db. Exception '" + e.getMessage() + "'", e);
    }
    return new AsyncResult<>(true);
  }

然后调用同一服务类中的sendSingleMessage方法,其中调用NOT跨国方法来进行数据库查找和添加数据库条目等。

当多次调用controllers @async方法而没有时间延迟时,会导致

org . spring framework . transaction . cannotcreatetransactionexception:无法打开事务的JPA EntityManager嵌套异常为org . hibernate . exception . jdbcconnectionexception:无法在获取JDBC连接...............org . spring framework . ORM . JPA . jpatransactionmanager . dobegin(jpatransactionmanager . Java:400)...65常见帧省略原因:Java . SQL . sqltransientconnection异常:HikariPool-1 -连接不可用,请求在30000毫秒后超时。在

需要用service @async方法添加“ThreadExecutor”吗?

我是这方面的新手,所以任何指示都会有帮助

共有2个答案

祖迪
2023-03-14

最有可能的原因是以下2个原因之一,即数据库是可连接的:

1)连接池的大小不足。< br >检查属性spring . data source . hikari . maximumpoolsize的值(默认值为20)以确保该数值足够。想想在你的应用程序中可以同时处理多少个请求,假设每个线程都使用自己的连接。

2) 应用程序中的连接泄漏
检查您的连接是否已正确关闭(在本例中返回池)。始终呼叫连接。finally块中的close()或使用try-with资源来避免异常泄漏。

彭弘伟
2023-03-14

我也有类似的情况。经过研究,我们发现异步线程正在压倒系统。所有线程都是并行启动的,这耗尽了JDBC连接池。没有为其他线程(如控制器)留下连接。

第一个措施是使用自定义线程执行器,您可以根据自己的资源进行限制。

    @Bean(name = "taskExecutor")
    public ExecutorService taskExecutor() {
        // adjust this value to your CPU cores
        // and to the JDBC connection pool size
        int maxThreads = 4;
        return Executors.newFixedThreadPool(maxThreads);
    }

确保此任务执行程序用于异步方法:

    @Async("taskExecutor")  
    public void myBackgroundThread() {
        ...
    }

在application.properties文件中,设置光数据源的连接池大小。默认值为10。

spring.datasource.hikari.maximum-pool-size=10

请注意,后台进程的线程池小于数据库连接的线程池。否则前台线程将受到影响。

 类似资料:
  • 我将Spring与JPA一起使用。我打开了和。在我的用户注册服务方法中,我调用了一些其他服务方法,它们被注释为。这些方法可以做各种事情,比如发送欢迎电子邮件和在我们的第三方支付系统中注册新创建的用户。 一切都很好,直到我想验证第三方支付系统是否成功创建了用户。此时,方法试图创建一个(引用新创建的),并出现 寄存器调用如下所示: 支付服务调用以完成其注册用户的工作,如下所示: 这里列出的StackO

  • 问题内容: 我有一种将用于发送电子邮件的方法。我想锁定此方法,以便每次只有一个线程可以访问它,其余线程同时存储。我应该同步方法还是使用spring @transactional PROPAGATION_REQUIRED? 在我的服务层 问题答案: 为什么不通过不使用任何实例级别的东西使该方法成为线程安全的呢? 但是,我看不到Spring的事务管理如何适合这里。我的意思是Spring提供几个事务管理

  • 问题内容: 在一个岛中,我有2个@Transactional方法。 如果我不提供任何明确的属性, 那会发生什么,如果 我在另一种体内运行一种方法? 两种方法都可以在同一交易中运行吗? 问题答案: 春季AOP中的代理 使用事务性时,您要处理类的代理,因此在这种情况下: 您从外部调用代理,但是第二个方法调用是从代理对象内部进行的,因此没有事务支持。所以自然地,它们运行在同一事务中,无论第二种方法中@T

  • 我正在使用带有webflux的spring boot 2.4.2连接到postgres数据库。我在使用事务性代码时观察到了一个我不理解的行为。 为了展示这种行为,我创建了一个示例应用程序,试图将行添加到两个表中;表“a”和表“b”。对表“a”的插入预计将失败,并出现重复密钥冲突。考虑到使用了事务性,我希望不会向表“b”中添加任何行。 然而,根据我用哪个方法注释事务,我会得到不同的结果。 如果我对c

  • 问题内容: 我在Service类中看到了一种被标记为的方法,但是它也在同一类中调用了其他未标为的方法。 这是否意味着对单独方法的调用导致应用程序打开与DB的单独连接或暂停父事务等? 不带任何注释的方法的默认行为是什么,而另一个带有注释的方法调用该方法的默认行为是什么? 问题答案: 当你调用没有事务块之内的方法时,父事务将继续使用新方法。它将使用与父方法(with )相同的连接,以及在调用的方法中导