简体   繁体   English

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

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

I have couple of routes (route 1 and route 2) in my Spring Boot application.我的 Spring Boot 应用程序中有几条路线(路线 1 和路线 2)。 I have been researching how to gracefully shutdown the application after processing both the routes.我一直在研究如何在处理完两条路由后正常关闭应用程序。 I have referred the documentation ( https://camel.apache.org/manual/latest/graceful-shutdown.html ) but couldn't successfully achieve what I needed.我已经参考了文档( https://camel.apache.org/manual/latest/graceful-shutdown.html )但无法成功实现我所需要的。 Maybe my understanding is wrong.可能我的理解有误。

Below are my two routes下面是我的两条路线

Route 1路线1

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

Route 2路线2

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

I have tried all these options我已经尝试了所有这些选项

1. Automatic shutdown after 60 seconds 1. 60秒后自动关机

camel.springboot.duration-max-seconds = 60

It does GRACEFULLY shutdown the 2 routes but then WARNs about FORCEFUL shutdown ExecutorsService and also it doesn't stop the main thread to stop the application.它确实优雅地关闭了 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. Initiate shutdown from the Route2 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" is gracefully stopped but "route2" fails to be gracefully stopped with below message and waits for default timeout (300s). “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]

It looks like there is a pending exchange message to be consumed.看起来有一个待处理的交换消息要消费。 Do I need to manually clear/consume the exchange message in order to clear and facilitate a graceful shutdown?我是否需要手动清除/使用交换消息以清除并促进正常关机?

Either option doesn't stop the main application.任一选项都不会停止主应用程序。 Do I have to write a custom Shutdown strategy instead of DefaultShutdownStrategy to achieve this?我是否必须编写自定义 Shutdown 策略而不是 DefaultShutdownStrategy 来实现此目的? Can someone kindly point to an example to shut down the Spring Boot application after completion of the routes?有人可以指出一个在路由完成后关闭 Spring Boot 应用程序的例子吗? Thanks in advance!!!提前致谢!!!

Did you try to use exchange.getContext().stop() to stop main application?您是否尝试使用exchange.getContext().stop()来停止主应用程序?

To force stop route without waiting for default timeout you can use exchange.getContext().stopRoute(routeId, 1L, TimeUnit.SECONDS);要强制停止路由而不等待默认超时,您可以使用exchange.getContext().stopRoute(routeId, 1L, TimeUnit.SECONDS); or set your timeout in seconds context.getShutdownStrategy().setTimeout(30);或以秒为单位设置超时context.getShutdownStrategy().setTimeout(30);

You have to stop the currently running route from a new thread.您必须从新线程中停止当前正在运行的路由。 The attached code is in Kotlin, but it should be easy to transfer it to Java:附加的代码在 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()

If you want to stop the entire application, you can use the following class and add a call of shutdownManager.initiateShutdown() after the exchange.context.stop() .如果要停止整个应用程序,可以使用以下类并在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