java - Spring Boot:通过控制涉及 MongoClient 的终止顺序来优雅关闭
问题描述
AsyncTaskExecutor
我有一个 Spring Boot 应用程序,它使用一个(数量是预定义的) 生成许多线程
线程执行一个无限循环,从一些队列和进程对象中读取,所以我并没有真正的拒绝策略机制(比如接受的 ThreadPool tasks
)
问题是当应用程序关闭时,线程可能(并且可能)忙于处理一个项目,其中包括使用MongoTemplate
.
因此,当应用程序关闭时,MongoClient 会close()
自动执行,然后我会从 Mongo 收到一些错误,例如:
java.lang.IllegalStateException: The pool is closed
at com.mongodb.internal.connection.ConcurrentPool.get(ConcurrentPool.java:137)
at com.mongodb.internal.connection.DefaultConnectionPool.getPooledConnection(DefaultConnectionPool.java:262)
at com.mongodb.internal.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:103)
at com.mongodb.internal.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:92)
at com.mongodb.internal.connection.DefaultServer.getConnection(DefaultServer.java:85)
如何优雅地关闭应用程序?例如,在不关闭 MongoClient 的同时中断线程?
代码:
豆子创建:
@Bean
AsyncTaskExecutor getTaskExecutor() {
SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
return executor;
}
只需通过以下方式执行:
executor.execute(runnable);
解决方案
不要使用SimpleAsyncTaskExecutor
- SimpleAsyncTaskExecutor 为每个请求创建一个新线程,而不是使用ThreadPoolTaskExecutor
和配置下面提到的两个属性。
/**
* Set whether to wait for scheduled tasks to complete on shutdown,
* not interrupting running tasks and executing all tasks in the queue.
* <p>Default is "false", shutting down immediately through interrupting
* ongoing tasks and clearing the queue. Switch this flag to "true" if you
* prefer fully completed tasks at the expense of a longer shutdown phase.
* <p>Note that Spring's container shutdown continues while ongoing tasks
* are being completed. If you want this executor to block and wait for the
* termination of tasks before the rest of the container continues to shut
* down - e.g. in order to keep up other resources that your tasks may need -,
* set the {@link #setAwaitTerminationSeconds "awaitTerminationSeconds"}
* property instead of or in addition to this property.
* @see java.util.concurrent.ExecutorService#shutdown()
* @see java.util.concurrent.ExecutorService#shutdownNow()
*/
public void setWaitForTasksToCompleteOnShutdown(boolean waitForJobsToCompleteOnShutdown) {
this.waitForTasksToCompleteOnShutdown = waitForJobsToCompleteOnShutdown;
}
/**
* Set the maximum number of seconds that this executor is supposed to block
* on shutdown in order to wait for remaining tasks to complete their execution
* before the rest of the container continues to shut down. This is particularly
* useful if your remaining tasks are likely to need access to other resources
* that are also managed by the container.
* <p>By default, this executor won't wait for the termination of tasks at all.
* It will either shut down immediately, interrupting ongoing tasks and clearing
* the remaining task queue - or, if the
* {@link #setWaitForTasksToCompleteOnShutdown "waitForTasksToCompleteOnShutdown"}
* flag has been set to {@code true}, it will continue to fully execute all
* ongoing tasks as well as all remaining tasks in the queue, in parallel to
* the rest of the container shutting down.
* <p>In either case, if you specify an await-termination period using this property,
* this executor will wait for the given time (max) for the termination of tasks.
* As a rule of thumb, specify a significantly higher timeout here if you set
* "waitForTasksToCompleteOnShutdown" to {@code true} at the same time,
* since all remaining tasks in the queue will still get executed - in contrast
* to the default shutdown behavior where it's just about waiting for currently
* executing tasks that aren't reacting to thread interruption.
* @see java.util.concurrent.ExecutorService#shutdown()
* @see java.util.concurrent.ExecutorService#awaitTermination
*/
public void setAwaitTerminationSeconds(int awaitTerminationSeconds) {
this.awaitTerminationSeconds = awaitTerminationSeconds;
}
相关部分
设置此执行程序在关闭时应该阻止的最大秒数,以便在容器的其余部分继续关闭之前等待剩余任务完成执行。如果您的剩余任务可能需要访问也由容器管理的其他资源,这将特别有用。
您可以使用 spring 自动配置来控制任务执行属性(首选)或使用@Bean
注释以编程方式进行配置
2.1.0 中的 Spring Boot 为任务执行器提供自动配置,并同时用于@EnableAsync
Spring MVC Async 支持。
应用程序不需要任务执行器 bean / webMvcConfigurer 配置。所以删除你有的,应该是好的。
您可以使用带有spring.task.execution.*
.
spring.task.execution.shutdown.await-termination=true
spring.task.execution.shutdown.await-termination-period=60
可以找到完整列表here
或者
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5);
taskExecutor.setMaxPoolSize(5);
taskExecutor.waitForTasksToCompleteOnShutdown(true);
taskExecutor.setAwaitTerminationSeconds(60);
return taskExecutor;
}
推荐阅读
- web-scraping - 抓取网站时出错
- matlab - creatjob 的作业数量,每个作业有 25 个工作人员读取数据和写入结果
- c# - 使用 LINQ c# 从 XML 整个节点获取
- sql-server - 根据 WHERE 的 IN 子句中的条目顺序对结果进行排序
- php - 如何在 CodeIgniter 中使用表单数据上传和验证图像?
- javascript - 标签应用程序。需要指导
- php - Laravel收到错误未定义的变量
- mysql - 关键字列中的全文搜索
- reactjs - 在传单矩形内添加文本
- python - pandaswide_to_long,id变量需要唯一标识每一行