前言
之前我有写过一篇文章,讲述的是怎么使用Dynamic-TP
做一些节省开发的一些问题,但是我感觉不能就直接这么算了,我还想看一下这个框架的一些内部逻辑,避免鸽太久自己以及忘了这回事情或者是还要花比较大的学习成本重新看一下源码,所以我打算花点时间狠狠的看下源码,整理一下自己认为有用的信息,毕竟要知其然更要知其所以然嘛~
我阅读的Dtp源码是1.1.9
之前使用Dynamic-TP
主要是为了使用它的以下功能:
- 动态调参
- 实时监控
- 通知告警
- 告警拓展
- 框架自带线程池
- 线程池注册
- 其他
所以我也打算从以下几个方面看下相关的一些源码
1、动态调参
虽然动态调参JDK1.8就自带的,但是实际上的Dynamic-TP
动态调参实际上有一定的修改的
据我观察Dynamic-TP
使用的是这组代码
private static void doRefresh(ExecutorWrapper executorWrapper, DtpExecutorProps props) {
ExecutorAdapter<?> executor = executorWrapper.getExecutor();
doRefreshPoolSize(executor, props);
if (!Objects.equals(executor.getKeepAliveTime(props.getUnit()), props.getKeepAliveTime())) {
executor.setKeepAliveTime(props.getKeepAliveTime(), props.getUnit());
}
if (!Objects.equals(executor.allowsCoreThreadTimeOut(), props.isAllowCoreThreadTimeOut())) {
executor.allowCoreThreadTimeOut(props.isAllowCoreThreadTimeOut());
}
// update queue
updateQueueProps(executor, props);
if (executorWrapper.isDtpExecutor()) {
doRefreshDtp(executorWrapper, props);
return;
}
doRefreshCommon(executorWrapper, props);
}
doRefreshPoolSize()
方法是修改核心线程数和最大线程数,期间涉及到核心线程是是要不如最大线程数大的,不然会报问题,最终调用JDK的修改参数的方法(不过实际上ThreadPoolExecutor本身就是支持校验核心线程数和最大线程数之间比较的)Objects.equals(executor.getKeepAliveTime(props.getUnit()), props.getKeepAliveTime()))
是由于配置文件里面默认是TimeUnit是秒,所以此处的比较还是根据秒做比较,当然Dynamic-TP
自己有自己的线程池
由于是修改的非核心线程的最大保活信息,底层修改的时候,会使用LockSupport、CAS方式关掉线程池(JBoss),或者是通过ReentrantLock遍历关闭对应超过最大时间的线程(Tomcat)
-
修改queue的时候,如果是内存安全线程则会修改最大使用内存,如果不相等才会修改任务队列;此外会修改 [OrderedDtpExecutor] 的信息
-
方法
doRefreshCommon
修改了拒绝策略等信息,并且如果有配置事件 -
AbstractDtpAdapter类监听了配置更新的事件,只有配置更新的时候才会调用以上的方法。出发方式的话,如果是nacos的话,则会通过某种方式实现的发布事件让Java程序监听。
该方式在CloudNacosRefresher中
@Override
public void onApplicationEvent(@NonNull ApplicationEvent event) {
if (needRefresh(((EnvironmentChangeEvent) event).getKeys())) {
refresh(environment);
}
}
2、实时监控
实时监控是通过DtpMonitor类实现的,此处实际上就是通过Spring的事件机制进行事件监控与触发。DtpMonitor自带一个定时任务线程池,最大线程数只有一个。DtpMonitor继承了OnceApplicationContextEventListener抽象类,这个类实现了以下方法
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (isOriginalEventSource(event) && event instanceof ApplicationContextEvent) {
if (event instanceof ContextRefreshedEvent) {
onContextRefreshedEvent((ContextRefreshedEvent) event);
} else if (event instanceof ContextStartedEvent) {
onContextStartedEvent((ContextStartedEvent) event);
} else if (event instanceof ContextStoppedEvent)