新增Class的加载缓存,解决频繁加载Class会使jvm的方法区空间不足导致OOM的问题;
This commit is contained in:
parent
e8436c88a3
commit
e6483c4b26
|
@ -1425,7 +1425,8 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
|
||||||
- 11、执行器回调日志落盘方案复用RPC序列化方案,并移除Jackson依赖;
|
- 11、执行器回调日志落盘方案复用RPC序列化方案,并移除Jackson依赖;
|
||||||
- 12、任务支持更换绑定执行器,方便任务分组转移和管理;
|
- 12、任务支持更换绑定执行器,方便任务分组转移和管理;
|
||||||
- 13、执行器热部署时JobHandler重新初始化,修复由此导致的 "jobhandler naming conflicts." 问题;
|
- 13、执行器热部署时JobHandler重新初始化,修复由此导致的 "jobhandler naming conflicts." 问题;
|
||||||
- 14、[迭代中]任务线程隔离:
|
- 14、新增Class的加载缓存,解决频繁加载Class会使jvm的方法区空间不足导致OOM的问题;
|
||||||
|
- 15、[迭代中]任务线程隔离:
|
||||||
- 执行器测异步响应,不存在阻塞不需要隔离;
|
- 执行器测异步响应,不存在阻塞不需要隔离;
|
||||||
- 调度中心共用单一调度线程池,可能导致调度阻塞需要线程隔离;调度线程池拆分为Fast/Slow两个,针对调度较慢的执行器地址请求,降级使用Slow线程池;考虑是否可以任务级隔离线程池;
|
- 调度中心共用单一调度线程池,可能导致调度阻塞需要线程隔离;调度线程池拆分为Fast/Slow两个,针对调度较慢的执行器地址请求,降级使用Slow线程池;考虑是否可以任务级隔离线程池;
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ public class ExecutorBizImpl implements ExecutorBiz {
|
||||||
// valid handler
|
// valid handler
|
||||||
if (jobHandler == null) {
|
if (jobHandler == null) {
|
||||||
try {
|
try {
|
||||||
IJobHandler originJobHandler = GlueFactory.getInstance().loadNewInstance(triggerParam.getJobId(), triggerParam.getGlueSource());
|
IJobHandler originJobHandler = GlueFactory.getInstance().loadNewInstance(triggerParam.getGlueSource());
|
||||||
jobHandler = new GlueJobHandler(originJobHandler, triggerParam.getGlueUpdatetime());
|
jobHandler = new GlueJobHandler(originJobHandler, triggerParam.getGlueUpdatetime());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error(e.getMessage(), e);
|
logger.error(e.getMessage(), e);
|
||||||
|
|
|
@ -33,9 +33,7 @@ public class GlueFactory {
|
||||||
* groovy class loader
|
* groovy class loader
|
||||||
*/
|
*/
|
||||||
private GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
|
private GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
|
||||||
|
private ConcurrentHashMap<String, Class<?>> CLASS_CACHE = new ConcurrentHashMap<>();
|
||||||
private static final ConcurrentHashMap<String, Class<?>> CLASS_CACHE = new ConcurrentHashMap<>();
|
|
||||||
private static final ConcurrentHashMap<Long, String> JOBID_MD5KEY_CACHE = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* load new instance, prototype
|
* load new instance, prototype
|
||||||
|
@ -44,9 +42,9 @@ public class GlueFactory {
|
||||||
* @return
|
* @return
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public IJobHandler loadNewInstance(long jobId, String codeSource) throws Exception{
|
public IJobHandler loadNewInstance(String codeSource) throws Exception{
|
||||||
if (codeSource!=null && codeSource.trim().length()>0) {
|
if (codeSource!=null && codeSource.trim().length()>0) {
|
||||||
Class<?> clazz = getCodeSourceClass(jobId, codeSource);
|
Class<?> clazz = getCodeSourceClass(codeSource);
|
||||||
if (clazz != null) {
|
if (clazz != null) {
|
||||||
Object instance = clazz.newInstance();
|
Object instance = clazz.newInstance();
|
||||||
if (instance!=null) {
|
if (instance!=null) {
|
||||||
|
@ -62,6 +60,22 @@ public class GlueFactory {
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException(">>>>>>>>>>> xxl-glue, loadNewInstance error, instance is null");
|
throw new IllegalArgumentException(">>>>>>>>>>> xxl-glue, loadNewInstance error, instance is null");
|
||||||
}
|
}
|
||||||
|
private Class<?> getCodeSourceClass(String codeSource){
|
||||||
|
try {
|
||||||
|
// md5
|
||||||
|
byte[] md5 = MessageDigest.getInstance("MD5").digest(codeSource.getBytes());
|
||||||
|
String md5Str = new BigInteger(1, md5).toString(16);
|
||||||
|
|
||||||
|
Class<?> clazz = CLASS_CACHE.get(md5Str);
|
||||||
|
if(clazz == null){
|
||||||
|
clazz = groovyClassLoader.parseClass(codeSource);
|
||||||
|
CLASS_CACHE.putIfAbsent(md5Str, clazz);
|
||||||
|
}
|
||||||
|
return clazz;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return groovyClassLoader.parseClass(codeSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* inject service of bean field
|
* inject service of bean field
|
||||||
|
@ -72,28 +86,4 @@ public class GlueFactory {
|
||||||
// do something
|
// do something
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<?> getCodeSourceClass(long jobId, String codeSource){
|
|
||||||
try {
|
|
||||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
|
||||||
byte[] md5 = md.digest(codeSource.getBytes());
|
|
||||||
BigInteger no = new BigInteger(1, md5);
|
|
||||||
String md5Str = no.toString(16);
|
|
||||||
Class<?> clazz = CLASS_CACHE.get(md5Str);
|
|
||||||
if(clazz == null){
|
|
||||||
clazz = groovyClassLoader.parseClass(codeSource);
|
|
||||||
Class<?> preClazz = CLASS_CACHE.putIfAbsent(md5Str, clazz);
|
|
||||||
|
|
||||||
// 如果代碼有變化則刪除之前class緩存
|
|
||||||
if(preClazz == null){
|
|
||||||
String preMd5 = JOBID_MD5KEY_CACHE.put(jobId, md5Str);
|
|
||||||
if(preMd5 != null){
|
|
||||||
CLASS_CACHE.remove(preMd5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return clazz;
|
|
||||||
} catch (Exception e) {
|
|
||||||
return groovyClassLoader.parseClass(codeSource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue