繁体   English   中英

Apache Camel Spring Boot - 处理路由后正常关闭应用程序

[英]Apache Camel Spring Boot - Graceful shutdown of the application after processing the routes

我的 Spring Boot 应用程序中有几条路线(路线 1 和路线 2)。 我一直在研究如何在处理完两条路由后正常关闭应用程序。 我已经参考了文档( https://camel.apache.org/manual/latest/graceful-shutdown.html )但无法成功实现我所需要的。 可能我的理解有误。

下面是我的两条路线

路线1

 from("timer://runOnce?repeatCount=1")
     .to("{{sql.selectAll}}")
......... SOME PROCESSING
     .to("direct:checkStatus")

路线2

from("direct:checkStatus")
     .delay(5000)
     .loopDoWhile(CONDITION)
          .process(DO_SOMETHING)
     .end()
     .to("jpa:com.pqr.MyClass)
     .stop();

我已经尝试了所有这些选项

1. 60秒后自动关机

camel.springboot.duration-max-seconds = 60

它确实优雅地关闭了 2 条路由,但随后会发出关于强制关闭 ExecutorsService 的警告,并且它也不会停止主线程来停止应用程序。

2020-03-01 18:28:25.507  WARN 30279 --- [otTerminateTask] o.a.c.i.e.BaseExecutorServiceManager     : Forcing shutdown of ExecutorService: org.apache.camel.util.concurrent.SizedScheduledExecutorService@17fbfb02[CamelSpringBootTerminateTask] due first await termination elapsed.
2020-03-01 18:28:25.507  WARN 30279 --- [otTerminateTask] o.a.c.i.e.BaseExecutorServiceManager     : Forcing shutdown of ExecutorService: org.apache.camel.util.concurrent.SizedScheduledExecutorService@17fbfb02[CamelSpringBootTerminateTask] due interrupted.
2020-03-01 18:28:25.508  INFO 30279 --- [otTerminateTask] o.a.c.i.e.BaseExecutorServiceManager     : Shutdown of ExecutorService: org.apache.camel.util.concurrent.SizedScheduledExecutorService@17fbfb02[CamelSpringBootTerminateTask] is shutdown: true and terminated: false took: 10.004 seconds.
2020-03-01 18:28:25.508  WARN 30279 --- [otTerminateTask] o.a.c.i.e.BaseExecutorServiceManager     : Forced shutdown of 1 ExecutorService's which has not been shutdown properly (acting as fail-safe)
2020-03-01 18:28:25.508  WARN 30279 --- [otTerminateTask] o.a.c.i.e.BaseExecutorServiceManager     :   forced -> org.apache.camel.util.concurrent.SizedScheduledExecutorService@17fbfb02[CamelSpringBootTerminateTask]

2.从Route2启动shutdown

    from("direct:checkStatus")
            .delay(5000)
            .loopDoWhile(CONDITION)
                 .process(DO_SOMETHING)
            .end()
            .to("jpa:com.pqr.MyClass)
            .process(exchange -> {
                exchange.getContext().getRouteController().stopRoute("route1");
                exchange.getContext().getRouteController().stopRoute("route2");
                System.out.println("Route1 -->"+exchange.getContext().getRouteController().getRouteStatus("route1"));
                System.out.println("Route2 -->"+exchange.getContext().getRouteController().getRouteStatus("route2"));
                exchange.getContext().shutdown();
            });

“route1”已正常停止,但“route2”无法正常停止并显示以下消息并等待默认超时(300 秒)。

2020-03-01 18:35:29.113  INFO 30504 --- [read #4 - Delay] o.a.c.i.engine.DefaultShutdownStrategy   : Starting to graceful shutdown 1 routes (timeout 300 seconds)
2020-03-01 18:35:29.116  INFO 30504 --- [ - ShutdownTask] o.a.c.i.engine.DefaultShutdownStrategy   : Route: route1 shutdown complete, was consuming from: timer://runOnce?repeatCount=1
2020-03-01 18:35:29.116  INFO 30504 --- [read #4 - Delay] o.a.c.i.engine.DefaultShutdownStrategy   : Graceful shutdown of 1 routes completed in 0 seconds
2020-03-01 18:35:29.117  INFO 30504 --- [read #4 - Delay] o.a.c.s.boot.SpringBootCamelContext      : Route: route1 is stopped, was consuming from: timer://runOnce?repeatCount=1
2020-03-01 18:35:29.117  INFO 30504 --- [read #4 - Delay] o.a.c.i.engine.DefaultShutdownStrategy   : Starting to graceful shutdown 1 routes (timeout 300 seconds)
2020-03-01 18:35:29.118  INFO 30504 --- [ - ShutdownTask] o.a.c.i.engine.DefaultShutdownStrategy   : Waiting as there are still 1 inflight and pending exchanges to complete, timeout in 300 seconds. Inflights per route: [route2 = 1]

看起来有一个待处理的交换消息要消费。 我是否需要手动清除/使用交换消息以清除并促进正常关机?

任一选项都不会停止主应用程序。 我是否必须编写自定义 Shutdown 策略而不是 DefaultShutdownStrategy 来实现此目的? 有人可以指出一个在路由完成后关闭 Spring Boot 应用程序的例子吗? 提前致谢!!!

您是否尝试使用exchange.getContext().stop()来停止主应用程序?

要强制停止路由而不等待默认超时,您可以使用exchange.getContext().stopRoute(routeId, 1L, TimeUnit.SECONDS); 或以秒为单位设置超时context.getShutdownStrategy().setTimeout(30);

您必须从新线程中停止当前正在运行的路由。 附加的代码在 Kotlin 中,但将其转移到 Java 应该很容易:

 fromF(route).id(routeId)
            .process(someProcessor)
            .to("jdbc:dataSource")
            .onCompletion()
            .choice().`when`(exchangeProperty("CamelBatchComplete"))
            .process(object : Processor {
                override fun process(exchange: Exchange) {
                    Thread {
                        try {
                            exchange.context.routeController.stopRoute(routeId)
                            exchange.context.stop()
                        } catch (e: Exception) {
                            throw RuntimeException(e)
                        }
                    }.start()

                }
            }
            )
            // must use end to denote the end of the onCompletion route
            .end()

如果要停止整个应用程序,可以使用以下类并在exchange.context.stop()之后添加shutdownManager.initiateShutdown()调用。

@Component
class ShutdownManager {

    companion object {
        val logger = LoggerFactory.getLogger(ShutdownManager::class.java)
    }

    @Autowired
    private val appContext: ApplicationContext? = null


    fun initiateShutdown(returnCode: Int) {
        logger.info("Shutting down with a Shutdown manager")
        SpringApplication.exit(appContext, ExitCodeGenerator { returnCode })
        System.exit(returnCode)
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM