使用Spring Boot执行器安全关闭rest服务器?
这是如何以正确的方式关闭Spring Boot应用程序的后续问题?
假设我们有一台服务器,当前连接了3个客户端,每个客户端都运行很长时间。 然后我们使用以下命令关闭服务器:
curl -X POST localhost:port/shutdown
那样做:
A)让服务器在关闭之前完成3个客户端正在运行的作业?
B)禁止发生任何其他连接,以便服务器最终关闭?
Spring Boot关闭端点调用此类: org.springframework.boot.actuate.endpoint.ShutdownEndpoint
,它在您的ApplicationContext
上调用close()
。 这反过来……
- 摧毁豆类
- 关闭豆厂
- 停止嵌入式servlet容器
如果您的bean已经订购并且已经仔细编写了关闭方法,那么这应该没问题。 但如果没有,那么在该关闭周期的某个时刻“3个客户端正在运行的作业”可能会被中断。 此外,您可能会在调用关闭和关闭周期之间的小时间窗口中建立新连接。
Spring提供应用程序事件和侦听器挂钩,允许您参与关闭周期。 ContextClosedEvent
是在销毁bean,嵌入式容器关闭等之前发布的,因此您可以在默认行为开始之前使用它来实现自己的关闭行为。例如:
public class ShutdownListener implements ApplicationListener { @Override public void onApplicationEvent(ContextClosedEvent event) { // } }
您可以实现此侦听器
- 使用HTTP 503拒绝连接请求(或者等同于您不处理HTTP请求的情况)
- 暂停以允许任何飞行作业在继续关闭循环之前完成
您以与在Spring Boot中注册任何ApplicationListener相同的方式注册此侦听器,例如
SpringApplication app = new SpringApplication(MyApplication.class); app.addListeners(new ShutdownListener());