You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优雅停止作为Windows服务运行的Quarkus应用避免崩溃误判

解决Quarkus作为Windows服务时优雅停止的问题

核心问题:调用Quarkus.asyncExit()会触发System.exit(),导致Windows服务被判定为崩溃,需要让应用在停止时返回控制权给启动线程而非直接退出JVM。

可行方案

1. 使用编程式QuarkusApplication控制生命周期

放弃直接调用Quarkus.run(),转而实现QuarkusApplication接口,手动控制应用的启动与停止流程,避免框架自动调用System.exit():

import io.quarkus.runtime.Quarkus;
import io.quarkus.runtime.QuarkusApplication;
import io.quarkus.runtime.annotations.QuarkusMain;

@QuarkusMain
public class WindowsServiceApp implements QuarkusApplication {
    private volatile boolean running = true;

    @Override
    public int run(String... args) throws Exception {
        // 启动Quarkus应用上下文
        Quarkus.run(args);
        
        // 阻塞直到停止信号触发
        while (running) {
            Thread.sleep(1000);
        }
        
        // 优雅关闭应用上下文
        Quarkus.close();
        return 0; // 返回而非调用System.exit()
    }

    // 供Windows服务停止时调用的方法
    public void stop() {
        running = false;
    }
}

这种方式下,Windows服务的stop方法只需调用WindowsServiceApp.stop(),让run方法自然结束并返回,不会触发System.exit(),Windows服务会被判定为正常停止。

2. 替换Quarkus默认的退出逻辑

通过自定义任务修改Quarkus的退出行为,避免调用System.exit():

  • 创建自定义ShutdownTask,注册到Quarkus生命周期中,在退出时完成资源清理后通知主线程结束:
import io.quarkus.runtime.ShutdownTask;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class CustomShutdownTask implements ShutdownTask {
    private final Runnable onShutdown;

    public CustomShutdownTask(Runnable onShutdown) {
        this.onShutdown = onShutdown;
    }

    @Override
    public void shutdown() {
        // 执行自定义资源清理逻辑
        // ...
        
        // 通知主线程结束阻塞
        onShutdown.run();
    }
}

在启动类中注册任务并阻塞等待停止信号:

public class WindowsServiceRunner {
    private volatile boolean running = true;

    public void start() {
        Quarkus.run(args -> {
            CustomShutdownTask shutdownTask = new CustomShutdownTask(() -> running = false);
            Quarkus.registerShutdownTask(shutdownTask);
            return 0;
        });

        // 阻塞直到收到停止信号
        while (running) {
            Thread.sleep(1000);
        }
    }

    public void stop() {
        // 触发Quarkus优雅关闭流程
        Quarkus.asyncExit();
    }
}

3. 避开System.exit()的配置调整

由于Java 17已废弃安全管理器,不推荐使用该方案。可尝试通过Quarkus配置调整退出行为:

  • 设置quarkus.shutdown.exit-code=-1(需验证版本兼容性),让Quarkus在退出时不调用System.exit(),但需配合自定义逻辑让主线程正确结束。

关键注意点

  • 确保Windows服务的stop方法仅触发Quarkus优雅关闭流程,而非直接终止进程。
  • 所有资源(数据库连接、线程池等)需在自定义ShutdownTask中完成清理,避免资源泄漏。

内容的提问来源于stack exchange,提问作者ewramner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 01:24:13