在启动生命周期中优雅地退出 quarkus

Ymo*_*Ymo 6 java quarkus

相关 zulip 聊天

我试图弄清楚在 quarkus 中应用程序启动期间应该如何优雅地失败。

  1. 我尝试将其添加到应用程序启动代码中。如果我运行其中一个单元测试,现在不会调用它。仅当我直接启动应用程序时才会调用它。我希望返回一个非零值,而不是抛出异常。这可能是推荐的方法。我不知道。
    public class MyApp implements QuarkusApplication {

        @Override
        public int run(String... args) throws Exception {
            System.out.println("Do startup logic here");
            Quarkus.waitForExit();
            return 0;
        }
Run Code Online (Sandbox Code Playgroud)
  1. 我还尝试从 onStart 生命周期事件中引发异常。但夸库斯似乎仍在继续执行
   void onStart(@Observes StartupEvent ev) {               
        LOGGER.info("The application is starting...");
    }

    void onStop(@Observes ShutdownEvent ev) {               
        LOGGER.info("The application is stopping...");
    }
Run Code Online (Sandbox Code Playgroud)

我不确定这是否是一个功能请求错误或者我遗漏了一些东西,这是正常行为。

编辑1:只是为了清楚:

@Startup
@ApplicationScoped
public class StarterBean {
    private static final Logger LOGGER = Logger.getLogger("");

    public StarterBean() {
        throw new RuntimeException("failed misrably");
    }
}
Run Code Online (Sandbox Code Playgroud)

当我使用“./gradlew quarkusDev”运行时,我在控制台中看到异常,但应用程序从未存在。我认为它应该存在。它确实在单元测试期间退出并正确失败。我尝试在 onStart 中移动异常,结果确实如此也没有帮助。我还尝试了 Startup、ApplicationScoped 或两者的组合

编辑2:

我通过构建 uber jar 并运行它来测试它。引发异常确实会退出应用程序。同样可以想象,应用程序在 docker 容器中运行时也会退出。我很困惑为什么 gradle 任务从来不存在。因此,为此我想我会接受答案。非常感谢你的帮助 !

Mic*_*rry 4

我不确定这里是否有一个很好的答案可以满足所有要求(如果我错了,很高兴得到纠正。)不确定您到底想要实现什么,但有一些选项可能值得探索:

  • Quarkus.asyncExit(code)在你的run()方法中将允许你优雅地退出,但这不会被单元测试调用。
  • 您可以在启动时初始化一个 bean(用 注释它@Startup),并在其构造函数中抛出异常,但这并不是特别优雅,并且无法让您控制状态代码。但它似乎确实返回 -1,因此它至少满足您的非零退出代码标准。(遗憾的Quarkus.asyncExit(code)是,它似乎不适用于单元测试,尽管它是在测试开始之前在 bean 初始化中执行的。)
  • 如上所述,但您可以System.exit()在 bean 构造函数中调用。这使您可以控制退出代码,但这是最不干净的方法,它只是将虚拟机拉走,而没有任何优雅的清理机会。

编辑:刚刚从 zulipchat 线程中看到了这一点,它添加了一些必要的上下文:

如果我看到某些条件(例如缺少环境变量或其他什么),我需要能够在启动过程中退出,我该怎么做?

在这种情况下,我可能会声明一个@Startup(或多个)bean 来根据这些环境变量进行初始化,并确保这些 bean 的构造函数在条件不正确时抛出有意义的异常(缺少环境变量、损坏的环境变量等) .) 这有几个优点:

  • 您可以将适当的启动检查分离到不同的 bean 中,从而强制执行职责分离;
  • 您有有意义的信息可供分析并在日志中采取行动;
  • 如果由于抛出该异常而出现问题,您可以有意义地以非零退出代码停止,从而允许容器运行状况检查系统报告节点已严重死亡。