【发布时间】:2009-10-08 12:41:26
【问题描述】:
我在 Tomcat 中有一个加载关键数据的初始化 servlet。有时需要中止某些错误的启动。
如何在不调用System.exit(1) 的情况下优雅地关闭已部署的应用程序/整个应用程序服务器
我想避免通过端口调用关闭 servlet,因为这在我的安装中没有配置。
可能有一些任务需要在 web.xml 中定义的关闭时从侦听器运行
【问题讨论】:
我在 Tomcat 中有一个加载关键数据的初始化 servlet。有时需要中止某些错误的启动。
如何在不调用System.exit(1) 的情况下优雅地关闭已部署的应用程序/整个应用程序服务器
我想避免通过端口调用关闭 servlet,因为这在我的安装中没有配置。
可能有一些任务需要在 web.xml 中定义的关闭时从侦听器运行
【问题讨论】:
首先,您永远不应该从 servlet 容器中调用 System.exit(),因为可能有其他应用程序在与您的进程相同的进程中运行,并且强行终止整个进程是非常不正确的。
假设您的“init servlet”实现了ServletContextListener,API/接口中没有定义正式的方式来向 servlet 容器发出信号“请巧妙地关闭应用程序”。但是,您可以从contextInitialized() 方法中抛出某种RuntimeException,这在大多数容器(至少是Tomcat)中会停止您的webapp 的启动并使其处于“停止”状态。但是我怀疑 Tomcat 是否会继续调用您的关闭侦听器。
您可能需要重新考虑您的设计,以便您的关键数据/关闭逻辑不会与 servlet 容器的生命周期紧密相关。
【讨论】:
System.exit 使服务器崩溃的习惯。
ServletContextListener 的实现不必是 Servlet,它可以是实现两个方法的接口的 POJO 类。顺便说一句,现在让 Servlet 容器识别、加载和执行侦听器的最简单方法是简单地使用 @WebListener 进行注释。这样的侦听器是您执行 Web 应用程序设置和拆卸的预期挂钩,保证在第一次/最后一次 servlet 调用之前/之后运行。
我添加的是一个运行状况检查探针,它将使用curl 检查服务器是否仍在运行,我认为可以对其进行修改以检查是否也存在“标志”文件。我只是发送一个catalina.sh stop 命令。
如果这是一个 Docker 容器,您可以使用 healthcheck 探针让它自己关闭。
理想情况下,如果您可以迁移到运行 tomcat 但如果 Spring 上下文未正确加载则终止它的 Spring Boot 之类的东西。
【讨论】: