我有几个Kafka消费者从Kafka集群中提取消息,然后他们将这些消息放入执行器服务中进行处理。消息本身的处理非常耗时。当我尝试关闭应用程序,也就是关闭Tomcat时,我注意到执行器服务将继续工作,但速度要慢得多,并且会出现一些套接字超时异常。这意味着我可能要等待很长时间才能完成Tomcat的关闭过程,但它只是继续运行。如果我手动终止Tomcat线程,那么我将丢失很多消息。我有办法解决这个问题吗?非常感谢!
线程池位于
执行器的线程池可以在其父应用程序结束后继续运行。因此,在退出应用程序时,您应该始终优雅地关闭执行器。
ServletContextListener
在基于Java Servlet技术的web应用程序的情况下,Servlet规范定义了web应用程序启动和退出的挂钩。
那个钩子就是ServletContextListener
接口。该接口需要两个方法,一个在处理对web应用程序的第一个传入请求之前由Servlet容器调用,另一个在发送最后一个响应之后调用。规范要求每个Servlet容器(如Tomcat)在适当的时间调用这些方法。
在这两个方法中,您可以实例化执行器服务,然后关闭它。
您可以通过编写一个类来实现接口。您还必须将该类标记到容器中。标记它的最简单方法是使用@WebListener
注释。
这已经在Stack Overflow上讨论过很多次了。所以搜索更多的信息和例子。
JSR 236:JavaTMEE的并发实用程序
如果使用成熟的Jakarta EE(以前的Java EE)实现(Glassfish、Payara、JBoss等),而不是仅仅使用Servlet容器(Tomcat、Jetty等),这项工作会容易得多。这样的服务器将提供JSR 236的实现,以自动处理执行者的生命周期。因此,您无需实现ServletContextListener
。
这个问题在Stack Overflow上也被解决了很多次。所以搜索更多信息。