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

Vert.x Java应用Shutdown Hook日志不全问题求助

问题

我们有一个Vert.x Java应用,需要在关闭时记录相关信息。但按下CTRL+C或关闭应用时,仅打印出“Shutting down...”这一条日志。相关代码如下:

Runtime.getRuntime().addShutdownHook(new Thread(serviceStatusLogger::log));

final Vertx vertx = Vertx.vertx();
final HttpServer server = vertx.createHttpServer();

final Router router = Router.router(Vertx.vertx());
final Route route = router.route(HttpMethod.GET, "/health");

route.handler(request -> {
    final HttpServerResponse response = request.response();
    response.putHeader("content-type", "text/plain");
    response.end(makeResponse());
});

server.requestHandler(router).listen(8085);

ServiceStatusLogger类代码:

public class ServiceStatusLogger {
    private static final Logger LOG = Logger.getLogger(ServiceStatusLogger.class.getName());

    private final DefaultMessageResolver defaultMessageResolver;
    private final WebhookResponseRepository webhookResponseRepository;

    public ServiceStatusLogger(final DefaultMessageResolver defaultMessageResolver,
                               final WebhookResponseRepository webhookResponseRepository) {
        this.defaultMessageResolver = defaultMessageResolver;
        this.webhookResponseRepository = webhookResponseRepository;
    }


    public void log(){

        LOG.info("Shutting down...");
        LOG.info("Last processed webhook response log id: " + webhookResponseRepository
                .getLastWebhookResponseLog()
                .getId());
        LOG.info("Total number of webhooks processed in this job execution: "
                + defaultMessageResolver.getWebhooksProcessed());
    }
}
解决方案

问题根源是你用了JVM原生的Runtime.shutdownHook,但Vert.x有自己的生命周期管理流程。当收到关闭信号时,Vert.x可能已经提前销毁了webhookResponseRepository或defaultMessageResolver依赖的资源,导致后续日志代码抛出未捕获异常,所以只输出了第一条日志。

按以下步骤调整即可解决:

  • 移除JVM shutdown hook,改用Vert.x的关闭回调
    Vert.x提供的vertx.closeHandler()会在Vert.x启动关闭流程时触发,此时所有Vert.x管理的资源还未被销毁,依赖对象仍可正常调用。

  • 修改代码绑定Vertx生命周期
    调整启动代码,注册Vert.x关闭处理器,并复用同一个Vertx实例创建路由(避免资源分散):

final Vertx vertx = Vertx.vertx();
final HttpServer server = vertx.createHttpServer();

// 注册Vert.x关闭回调
vertx.closeHandler(v -> {
    serviceStatusLogger.log();
});

// 复用已创建的vertx实例,不要重新调用Vertx.vertx()
final Router router = Router.router(vertx);
final Route route = router.route(HttpMethod.GET, "/health");

route.handler(request -> {
    final HttpServerResponse response = request.response();
    response.putHeader("content-type", "text/plain");
    response.end(makeResponse());
});

server.requestHandler(router).listen(8085);
  • 添加异常捕获(推荐)
    为防止log()方法中出现异常导致日志中断,可在回调中捕获异常:
vertx.closeHandler(v -> {
    try {
        serviceStatusLogger.log();
    } catch (Exception e) {
        LOG.severe("Failed to log shutdown status: " + e.getMessage());
    }
});

调整后,应用关闭时会先执行完整的日志记录逻辑,再逐步销毁资源,所有日志就能正常打印。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 20:56:29