在使用 Spring Batch 进行项目的过程中,我遇到了以下问题。该项目包括:
- MySQL 数据库 (mysqld 10.2.13-MariaDB)
- Spring Boot(2.1.1.RELEASE)
- 春季批次(4.1.0.RELEASE)
- Spring Batch 配置为使用与 JobRepository 的业务逻辑相同的数据源
数据源的 hikari 连接池大小配置为 4(这是将应用程序推送到我们的 CloudFoundry 实例并在 Spring 自动重新配置期间注入时的默认值)
作为参考,您可以查看示例项目,我在其中创建了一个最小项目来重现问题:https://github.com/FlorianSW/spring-batch-connection-issue https://github.com/FlorianSW/spring-batch-connection-issue
问题:
假设您有一个控制器,它处理一个 RequestMapping,其中至少发生两件事:控制器对业务模型数据库模式执行任意操作(例如,从数据库保存或请求实体),然后通过以下方式启动 Spring Batch 作业:对 JobLauncher#run 的调用。 Spring Batch 配置为使用池大小为 1 的 ThreadPoolTaskExecutor 异步运行任务。
如果请求映射每秒只查询几次(大约 1-3 次),那么这种方法效果很好。然而,如果映射被查询的次数超过这个数量,假设以同步方式(如果在本地测试)超过 4 次(在测试期间我使用了 4 个请求,最多 20 个请求),那么请求就会陷入死锁,其中一些请求会发生死锁。将被中止,但出现以下异常:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataAccessResourceFailureException: Could not obtain last_insert_id(); nested exception is java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 5001ms.]
当将连接池的大小增加到至少 7 时,这个问题可以得到缓解(我不知道这个数字来自哪里)。重新启动应用程序并执行我的测试 JavaScript 代码 [1] 来分派多个请求后,我可以轻松地将获取请求的数量增加到 150 个,并且应用程序将毫无问题地处理这些请求(如预期)。在增加池大小之前,大量请求会遇到超时。
我不确定这是否属于错误或改进或其他什么,并且我不确定该组件是否是文档或类似的东西,但是,我对此问题的意图是:
找出 Spring Batch 与 Spring Boot 一起是否需要数据库连接池中的最小可用连接数?如果是这样,是否应该在文档中提及?
或者,如果这是一个错误,因为请求处理期间使用的 JDBC 连接没有在合理的短时间内返回到池中?
[1]
for (i = 0; i <= 150; i++) {fetch('http://localhost:8080/api/jobs/' + i, {method: 'PUT'})}