如何防止 Spring 启动 daemon/server 应用程序 closing/shutting 立即关闭?
How to prevent Spring Boot daemon/server application from closing/shutting down immediately?
我的 Spring 启动应用程序不是 Web 服务器,而是使用自定义协议的服务器(在本例中使用 Camel)。
但是 Spring 引导在启动后立即停止(优雅地)。我该如何防止这种情况?
我希望应用程序在 Ctrl+C 或以编程方式停止时停止。
@CompileStatic
@Configuration
class CamelConfig {
@Bean
CamelContextFactoryBean camelContext() {
final camelContextFactory = new CamelContextFactoryBean()
camelContextFactory.id = 'camelContext'
camelContextFactory
}
}
对于 springboot 应用程序 运行 continously 它必须 运行 在一个容器中,否则它就像任何 java 应用程序一样所有线程都完成它完成,
您可以添加
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
它会把它变成 webapp,否则你有责任在你的实现中保持它的活力
我找到了解决方案,使用 org.springframework.boot.CommandLineRunner
+ Thread.currentThread().join()
,例如:
(注意:下面的代码在 Groovy,而不是 Java)
package id.ac.itb.lumen.social
import org.slf4j.LoggerFactory
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
@SpringBootApplication
class LumenSocialApplication implements CommandLineRunner {
private static final log = LoggerFactory.getLogger(LumenSocialApplication.class)
static void main(String[] args) {
SpringApplication.run LumenSocialApplication, args
}
@Override
void run(String... args) throws Exception {
log.info('Joining thread, you can press Ctrl+C to shutdown application')
Thread.currentThread().join()
}
}
Spring Boot 将 运行 应用程序的任务留给实现应用程序的协议。例如,参见 guide:
Also required are some housekeeping objects like a CountDownLatch
to keep the main thread alive...
因此,例如,运行设置 Camel 服务的方式是 运行 Camel 作为 standalone application 从您的主要 Spring 启动应用程序class.
使用 CountDownLatch 的示例实现:
@Bean
public CountDownLatch closeLatch() {
return new CountDownLatch(1);
}
public static void main(String... args) throws InterruptedException {
ApplicationContext ctx = SpringApplication.run(MyApp.class, args);
final CountDownLatch closeLatch = ctx.getBean(CountDownLatch.class);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
closeLatch.countDown();
}
});
closeLatch.await();
}
现在要停止您的应用程序,您可以查找进程 ID 并从控制台发出 kill 命令:
kill <PID>
从 Apache Camel 2.17 开始,有一个更清晰的答案。引用 http://camel.apache.org/spring-boot.html:
To keep the main thread blocked so that Camel stays up, either include the spring-boot-starter-web dependency, or add camel.springboot.main-run-controller=true to your application.properties or application.yml file.
您还需要以下依赖项:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>2.17.0</version>
</dependency>
明确替换 <version>2.17.0</version>
或使用 camel BOM 导入依赖管理信息以保持一致性。
要在未部署 Web 应用程序时保持 java 进程处于活动状态,请将 webEnvironment 属性 设置为 false,如下所示:
SpringApplication sa = new SpringApplication();
sa.setWebEnvironment(false); //important
ApplicationContext ctx = sa.run(ApplicationMain.class, args);
我的项目是NON WEB Spring Boot。
我的优雅解决方案是通过 CommandLineRunner 创建一个守护线程。
然后,应用程序不会立即关闭。
@Bean
public CommandLineRunner deQueue() {
return args -> {
Thread daemonThread;
consumer.connect(3);
daemonThread = new Thread(() -> {
try {
consumer.work();
} catch (InterruptedException e) {
logger.info("daemon thread is interrupted", e);
}
});
daemonThread.setDaemon(true);
daemonThread.start();
};
}
所有线程执行完毕,程序会自动关闭。
因此,使用 @Scheduled
注册一个空任务将创建一个循环线程以防止关闭。
现在变得更简单了。
只需将 camel.springboot.main-run-controller=true
添加到您的 application.properties
我的 Spring 启动应用程序不是 Web 服务器,而是使用自定义协议的服务器(在本例中使用 Camel)。
但是 Spring 引导在启动后立即停止(优雅地)。我该如何防止这种情况?
我希望应用程序在 Ctrl+C 或以编程方式停止时停止。
@CompileStatic
@Configuration
class CamelConfig {
@Bean
CamelContextFactoryBean camelContext() {
final camelContextFactory = new CamelContextFactoryBean()
camelContextFactory.id = 'camelContext'
camelContextFactory
}
}
对于 springboot 应用程序 运行 continously 它必须 运行 在一个容器中,否则它就像任何 java 应用程序一样所有线程都完成它完成, 您可以添加
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
它会把它变成 webapp,否则你有责任在你的实现中保持它的活力
我找到了解决方案,使用 org.springframework.boot.CommandLineRunner
+ Thread.currentThread().join()
,例如:
(注意:下面的代码在 Groovy,而不是 Java)
package id.ac.itb.lumen.social
import org.slf4j.LoggerFactory
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
@SpringBootApplication
class LumenSocialApplication implements CommandLineRunner {
private static final log = LoggerFactory.getLogger(LumenSocialApplication.class)
static void main(String[] args) {
SpringApplication.run LumenSocialApplication, args
}
@Override
void run(String... args) throws Exception {
log.info('Joining thread, you can press Ctrl+C to shutdown application')
Thread.currentThread().join()
}
}
Spring Boot 将 运行 应用程序的任务留给实现应用程序的协议。例如,参见 guide:
Also required are some housekeeping objects like a
CountDownLatch
to keep the main thread alive...
因此,例如,运行设置 Camel 服务的方式是 运行 Camel 作为 standalone application 从您的主要 Spring 启动应用程序class.
使用 CountDownLatch 的示例实现:
@Bean
public CountDownLatch closeLatch() {
return new CountDownLatch(1);
}
public static void main(String... args) throws InterruptedException {
ApplicationContext ctx = SpringApplication.run(MyApp.class, args);
final CountDownLatch closeLatch = ctx.getBean(CountDownLatch.class);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
closeLatch.countDown();
}
});
closeLatch.await();
}
现在要停止您的应用程序,您可以查找进程 ID 并从控制台发出 kill 命令:
kill <PID>
从 Apache Camel 2.17 开始,有一个更清晰的答案。引用 http://camel.apache.org/spring-boot.html:
To keep the main thread blocked so that Camel stays up, either include the spring-boot-starter-web dependency, or add camel.springboot.main-run-controller=true to your application.properties or application.yml file.
您还需要以下依赖项:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>2.17.0</version>
</dependency>
明确替换 <version>2.17.0</version>
或使用 camel BOM 导入依赖管理信息以保持一致性。
要在未部署 Web 应用程序时保持 java 进程处于活动状态,请将 webEnvironment 属性 设置为 false,如下所示:
SpringApplication sa = new SpringApplication();
sa.setWebEnvironment(false); //important
ApplicationContext ctx = sa.run(ApplicationMain.class, args);
我的项目是NON WEB Spring Boot。 我的优雅解决方案是通过 CommandLineRunner 创建一个守护线程。 然后,应用程序不会立即关闭。
@Bean
public CommandLineRunner deQueue() {
return args -> {
Thread daemonThread;
consumer.connect(3);
daemonThread = new Thread(() -> {
try {
consumer.work();
} catch (InterruptedException e) {
logger.info("daemon thread is interrupted", e);
}
});
daemonThread.setDaemon(true);
daemonThread.start();
};
}
所有线程执行完毕,程序会自动关闭。
因此,使用 @Scheduled
注册一个空任务将创建一个循环线程以防止关闭。
现在变得更简单了。
只需将 camel.springboot.main-run-controller=true
添加到您的 application.properties