Arm*_*ine 5 java mysql multithreading amazon-web-services amazon-aurora
我有一个用于 cron 任务的 Spring Boot 应用程序。其中一个任务作为一组异步执行的多个线程来执行。每个线程都会在 MySQL 兼容的 AWS Aurora Serverless DB 中插入约 200K 数据。在任务完成之前,所有线程都在完成后关闭,但MySQL中相应的进程仍以“睡眠”状态保留在进程列表中。这是缩短的示例:
@SpringBootApplication
@EnableScheduling
public class ScheduledServiceApp implements SchedulingConfigurer {
private static final int POOL_SIZE = 20;
public static void main(String[] args) {
SpringApplication.run(ScheduledServiceApp.class, args);
}
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(POOL_SIZE);
threadPoolTaskScheduler.setThreadNamePrefix("scheduled-task-pool-");
threadPoolTaskScheduler.initialize();
scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
}
}
@Component
public class ScheduledTask {
// .....
@Scheduled(cron = "${task.cron.expression}", zone="UTC")
// @Modifying(clearAutomatically = true, flushAutomatically = true)
@Transactional
public void runTask() {
try {
// .....
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; ++i) {
Runnable task = new TaskThread();
executor.execute(task);
}
executor.shutdown();
while (!executor.awaitTermination(1, TimeUnit.SECONDS)) {
// wait until the processes in the executor will be terminated
}
log.info("Task is completed successfully");
} catch (Exception e) {
// log the error
}
}
}
public class TaskThread implements Runnable {
// .....
public void run() {
dataService.insertData(/* parameters */);
}
}
Run Code Online (Sandbox Code Playgroud)
每个单独的线程执行可能会持续约 30 分钟,因为要处理的数据量很大,任务完成后,在 MySQL 控制台中我仍然看到相应的进程处于“睡眠”模式,并且仅在超时后才终止值达到。
正如您在代码中看到的,@Modifying带有参数的注释也没有帮助。另外,我不想减少超时值,因为这也可能会影响直接在 MySQL 中运行的查询。但我想终止这些进程,因为它们会影响应用程序的整体性能。
所以我的问题是:是否有一个解决方案可以使 MySQL 进程在我的任务完成时终止而不是休眠?
更新:忘记提及该应用程序完全由容器管理并在 Tomcat 下运行。适用于 MySQL 的 JDBC/ODBC 桥(兼容 Aurora Serverless MySQL 5.7)。
默认情况下,Spring Boot 应用程序使用 HikariCP 进行连接池。因此基本上 HikariCP 负责数据库连接生命周期。因此,当您的一个线程尝试执行任何与数据库相关的操作(例如向数据库读取或写入数据)时,它会要求 HikariCP 为其提供一个连接,因为连接创建过程非常慢并且需要大量资源,HikariCP 默认情况下会保留池中的连接持续配置的时间。因此,您需要参考HikariCP文档maxLifetime中的和属性。idleTimeout
application.properties当您使用 Spring Boot 时,您可以使用以下配置选项从文件中控制 HikariCP 。
spring.datasource.hikari.minimum-idle=XXXX
spring.datasource.hikari.max-lifetime=XXX
Run Code Online (Sandbox Code Playgroud)
所有线程在完成后都将被关闭,但 MySQL 中相应的进程仍以“睡眠”状态保留在进程列表中
Spring boot 使用 HikariCP 作为默认数据库连接池。当事务关闭时,连接不会关闭。相反,数据库连接将返回到连接池。因此,MySQL 必须显示那些空闲连接。
所以我的问题是:是否有一个解决方案可以使 MySQL 进程在我的任务完成时终止而不是休眠?
如果不使用连接池,则所有连接将在需要时打开,并在事务完成时关闭。MySQL 将不会显示这些睡眠进程。请尝试以下设置来禁用连接池 -
spring.datasource.type=org.springframework.jdbc.datasource.SimpleDriverDataSource
Run Code Online (Sandbox Code Playgroud)
但是,如果禁用数据库连接池,则会有缺点 -
我建议您找出您的应用程序需要多少个并发连接。然后微调 HikariCP 连接池属性spring.datasource.hikari.maximum-pool-size,使连接池不会影响应用程序性能。
| 归档时间: |
|
| 查看次数: |
943 次 |
| 最近记录: |