【问题标题】:Apache Camel Spring Boot - Graceful shutdown of the application after processing the routesApache Camel Spring Boot - 处理路由后优雅关闭应用程序
【发布时间】:2020-06-14 07:11:11
【问题描述】:

我的 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 启动关闭

    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]

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

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

【问题讨论】:

  • 我认为您可以获取 SpringApplicationContext 并在传递上下文时调用应用程序的退出方法,如下所示:baeldung.com/spring-boot-shutdown#exit,一旦过程完成就执行此操作

标签: spring-boot apache-camel spring-camel


【解决方案1】:

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

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

【讨论】:

  • 嗨,是的,我确实尝试过使用 exchange.getContext().stop();作为我路线2的最后一步。它仍然显示“正在等待,因为仍有 1 次飞行和等待交换完成”。我是否需要在启动停止序列之前删除交换消息?
  • 嗨。您可以尝试在停止上下文之前清理飞行存储库access.redhat.com/webassets/avalon/d/red-hat-jboss-fuse/6.3/…,但待处理的交换可能会保留。最可靠的选择是强制关闭所有路由或减少关闭超时,我在答案中写过。
【解决方案2】:

您必须从一个新线程停止当前正在运行的路由。 onCompletion() DSL 是为了确保每条消息都得到处理。

附上的代码在 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)
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 2016-06-09
    • 1970-01-01
    • 2017-07-05
    • 2019-09-26
    • 2016-06-17
    相关资源
    最近更新 更多