如何正确重启Spring Boot应用程序?

时间:2019-01-24 08:11:33

标签: java spring-boot tomcat

我正在使用here中的代码来重新启动Spring Boot应用程序:

Thread restartThread = new Thread(() -> restartEndpoint.restart());
restartThread.setDaemon(false);
restartThread.start();

但是,重新启动的应用程序无法创建Bean,最终是由于尝试安排带有RejectedExecutionException注释的方法时抛出了@Scheduled

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myBean' defined in URL [insert-path-here]: Initializetion of bean failed; nested exception is org.springframework.core.TaskRejectedException: Executor [java.util.concurrent.ScheduledThreadPoolExecutor@284a4a89[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 21508]] did not accept task: my.package.MyBean.scheduledMethod

doRestart()调用之后的日志表明ExecutorService taskScheduler正在关闭,这可以解释为什么会发生这种情况。我不确定的是为什么不重新创建ExecutorService。令人尴尬的是,事实证明taskScheduler是我的应用程序定义的bean,没有注释@RefreshScope。现在我得到的错误是

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'anotherBean' definen in URL[...]: Unsatisfied dependency expressed through constructor parameter 0 ... nested exception is  java.lang.IllegalStateException: org.springframework.boot.servlet.context.AnnotationConfigServletWebServerApplicationContext@2a95076c has been closed already

在日志中向上滚动会发现有一个ApplicationContextException与包含doRestart的堆栈跟踪一起抛出:

org.springframework.ApplicationContextException: Unable to start web server; nested exception is java.lang.IllegalStateException: Filters cannot be added to context [/myapp] as the context has been initialized
    at org.springframework.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:157)
    ...
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
    at org.springframework.cloud.context.restart.RestartEndpoint(RestartEndpoint.java:160)
    at my.package.MyBean.lambda$doThingAndRestart$2 (MyBean.java: 118)

搜索该错误似乎会导致single page无关紧要,尽管我确实注意到该应用程序也在Tomcat上运行。

我怀疑这与应用程序创建错误的应用程序上下文有关,该上下文是AnnotationConfigServletWebServerApplicationContext,没有扩展AbstractRefreshableAplicationContext

我该怎么办才能消除此错误?

当我仅从堆栈跟踪中复制单行时,请忍受我。我使用的是两台计算机,因此无法复制和粘贴,也不允许将日志移动到连接到Internet的计算机上。

1 个答案:

答案 0 :(得分:0)

事实证明,RestartEndpoint仅适用于Spring的内部Tomcat,不适用于外部的Tomcat。因此,需要另一种解决方案。我发现的是

  • 在覆盖配置文件时,使用Tomcat的WatchedResource重新部署服务器。缺点是在维护doThingAndRestart功能时需要维护Tomcat配置。
  • 使用Tomcat的Manager App。我注意到reload请求一直阻塞,直到应用程序完成重新加载为止,这使堆空间溢出。
  • 使用Spring的RefreshEndpoint。出于某种原因,这并没有刷新数据源。