赞
踩
1.Tomcat接受请求是通过Connector组件,而这个组件本身实现了LifeCycle接口,它是可以被暂停的,暂停过程只停止接受请求,但不会关闭容器本身。
因此,优雅停机,应该是先暂停 Tomcat 的 Connector,然后再等待执行线程执行完成,最后停止。
2.同时layering-cache里StatsService的静态变量ScheduledThreadPoolExecutor也被停掉的
3.热部署 只是将最新的class 装载到另一个classloader,tomcat实际没有重启
1.热部署restartedMain线程重新Initializing ExecutorService
2.重新create bean时layering-cache里用的线程池触发拒绝策略,因为此时这里的ScheduledThreadPoolExecutor处于Terminated死亡状态,该状态不能不会切换到其他任何状态。
3.线程池会拒绝任何想要加入的任务。因为这里用的还是同一个running jvm的方法区的静态变量ScheduledThreadPoolExecutor,也是Tomcat优雅停机时 shutdown掉的线程池
思路是在create bean layeringCacheManager初始化前,使用BeanPostProcessor,获取layering-cache框架中BeanFactory的StatsService,通过反射修改静态变量ScheduledThreadPoolExecutor
import com.github.xiaolyuh.stats.StatsService; import com.github.xiaolyuh.util.NamedThreadFactory; import com.sun.istack.Nullable; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; import org.springframework.stereotype.Component; import java.lang.reflect.Field; import java.util.concurrent.ScheduledThreadPoolExecutor; /** * @Description 解决SpringBoot热部署时layering-cache线程池被Tomcat Graceful shutdown, * 重新赋值方法区中 StatsService的Static ScheduledThreadPoolExecutor,以免初始化Bean时Terminated线程触发拒绝策略 * @Author fuly2 * @date 2022-02-18 13:50 **/ @Component public class StatesBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements BeanFactoryAware { @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException {} @Override @Nullable public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if ("layeringCacheManager".equals(beanName)) { StatsService statsService = com.github.xiaolyuh.util.BeanFactory.getBean(StatsService.class); Field executor = null; try { executor = statsService.getClass().getDeclaredField("executor"); } catch (NoSuchFieldException e) { e.printStackTrace(); } executor.setAccessible(true); try { ScheduledThreadPoolExecutor executor2= (ScheduledThreadPoolExecutor) executor.get(statsService); if (executor2.isTerminated()){ executor.set(statsService,new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("layering-cache-stat"))); } } catch (IllegalAccessException e) { e.printStackTrace(); } } return null; } }
1.layering-cache是一个支持分布式环境的多级缓存框架,使用方式和spring-cache类似。
2.一级缓存使用Caffeine作为本地缓存,二级缓存使用redis作为集中式缓存。一级缓存和二级缓存的数据一致性是通过推和拉两种模式相结合的方式来实现的。推主要是基于redis的pub/sub机制,拉主要是基于消息队列和记录消费消息的偏移量来实现的。
Terminated是一个线程的最终状态,在该状态中线程不会切换到其他任何状态,线程进入Terminated状态,意味着该线程的整个生命周期都结束了,下列这些情况将会使线程进入Terminated状态。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。