Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
X
XXL-JOB
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
靳帅
XXL-JOB
Commits
39470eab
提交
39470eab
authored
3月 12, 2016
作者:
xueli.xue
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
1、支持实时查询详细执行日志;
2、支持远程任务终止;
上级
ee9eca0d
隐藏空白字符变更
内嵌
并排
正在显示
18 个修改的文件
包含
518 行增加
和
53 行删除
+518
-53
README.md
README.md
+1
-0
JobLogController.java
...rc/main/java/com/xxl/job/controller/JobLogController.java
+76
-0
JobMonitorHelper.java
...c/main/java/com/xxl/job/core/thread/JobMonitorHelper.java
+5
-0
RemoteHttpJobBean.java
.../main/java/com/xxl/job/service/job/RemoteHttpJobBean.java
+1
-0
XxlJobLogMapper.xml
...min/src/main/resources/mybatis-mapper/XxlJobLogMapper.xml
+1
-1
index.ftl
...-admin/src/main/webapp/WEB-INF/template/jobinfo/index.ftl
+1
-1
index.ftl
...b-admin/src/main/webapp/WEB-INF/template/joblog/index.ftl
+1
-0
logdetail.ftl
...min/src/main/webapp/WEB-INF/template/joblog/logdetail.ftl
+7
-0
jobinfo.index.1.js
xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js
+10
-11
joblog.index.1.js
xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js
+79
-4
DemoJobHandler.java
...main/java/com/xxl/job/service/handler/DemoJobHandler.java
+4
-2
log4j.properties
xxl-job-client-demo/src/main/resources/log4j.properties
+0
-10
log4j.xml
xxl-job-client-demo/src/main/resources/log4j.xml
+47
-0
HandlerRepository.java
...in/java/com/xxl/job/client/handler/HandlerRepository.java
+86
-21
HandlerThread.java
...c/main/java/com/xxl/job/client/handler/HandlerThread.java
+17
-1
XxlJobFileAppender.java
.../main/java/com/xxl/job/client/log/XxlJobFileAppender.java
+180
-0
XxlJobJettyServerHandler.java
...xxl/job/client/netcom/jetty/XxlJobJettyServerHandler.java
+1
-1
XxlJobServlet.java
...java/com/xxl/job/client/netcom/servlet/XxlJobServlet.java
+1
-1
没有找到文件。
README.md
浏览文件 @
39470eab
...
...
@@ -17,6 +17,7 @@ git.osc地址:http://git.oschina.net/xuxueli0323/xxl-job
7、支持任务执行日志;
8、支持自定义参数;
9、支持任务失败次数超阈值邮件报警;
10、支持在线查看,执行器详细日志;
# 新版本 V1.2.x,新特性
1、支持任务分组;
...
...
xxl-job-admin/src/main/java/com/xxl/job/controller/JobLogController.java
浏览文件 @
39470eab
...
...
@@ -16,8 +16,12 @@ import org.springframework.web.bind.annotation.RequestMapping;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
com.xxl.job.client.handler.HandlerRepository
;
import
com.xxl.job.client.util.HttpUtil
;
import
com.xxl.job.client.util.HttpUtil.RemoteCallBack
;
import
com.xxl.job.client.util.JacksonUtil
;
import
com.xxl.job.core.constant.Constants.JobGroupEnum
;
import
com.xxl.job.core.model.ReturnT
;
import
com.xxl.job.core.model.XxlJobLog
;
import
com.xxl.job.dao.IXxlJobLogDao
;
...
...
@@ -88,4 +92,76 @@ public class JobLogController {
return
callBack
;
}
@RequestMapping
(
"/logDetail"
)
@ResponseBody
public
ReturnT
<
String
>
logDetail
(
int
id
){
// base check
XxlJobLog
log
=
xxlJobLogDao
.
load
(
id
);
if
(
log
==
null
)
{
return
new
ReturnT
<
String
>(
500
,
"参数异常"
);
}
// server address
@SuppressWarnings
(
"unchecked"
)
Map
<
String
,
String
>
jobDataMap
=
JacksonUtil
.
readValue
(
log
.
getJobData
(),
Map
.
class
);
String
handler_address
=
jobDataMap
.
get
(
HandlerRepository
.
HANDLER_ADDRESS
);
if
(!
handler_address
.
startsWith
(
"http"
)){
handler_address
=
"http://"
+
handler_address
+
"/"
;
}
// trigger id, trigger time
Map
<
String
,
String
>
reqMap
=
new
HashMap
<
String
,
String
>();
reqMap
.
put
(
HandlerRepository
.
NAMESPACE
,
HandlerRepository
.
NameSpaceEnum
.
LOG
.
name
());
reqMap
.
put
(
HandlerRepository
.
TRIGGER_LOG_ID
,
String
.
valueOf
(
id
));
reqMap
.
put
(
HandlerRepository
.
TRIGGER_TIMESTAMP
,
String
.
valueOf
(
log
.
getTriggerTime
().
getTime
()));
RemoteCallBack
callBack
=
HttpUtil
.
post
(
handler_address
,
reqMap
);
if
(
HttpUtil
.
RemoteCallBack
.
SUCCESS
.
equals
(
callBack
.
getStatus
()))
{
return
new
ReturnT
<
String
>(
callBack
.
getMsg
());
}
else
{
return
new
ReturnT
<
String
>(
500
,
callBack
.
getMsg
());
}
}
@RequestMapping
(
"/logDetailPage"
)
public
String
logDetailPage
(
int
id
,
Model
model
){
ReturnT
<
String
>
data
=
logDetail
(
id
);
model
.
addAttribute
(
"result"
,
data
);
return
"joblog/logdetail"
;
}
@RequestMapping
(
"/logKill"
)
@ResponseBody
public
ReturnT
<
String
>
logKill
(
int
id
){
// base check
XxlJobLog
log
=
xxlJobLogDao
.
load
(
id
);
if
(
log
==
null
)
{
return
new
ReturnT
<
String
>(
500
,
"参数异常"
);
}
// server address
@SuppressWarnings
(
"unchecked"
)
Map
<
String
,
String
>
jobDataMap
=
JacksonUtil
.
readValue
(
log
.
getJobData
(),
Map
.
class
);
String
handler_address
=
jobDataMap
.
get
(
HandlerRepository
.
HANDLER_ADDRESS
);
if
(!
handler_address
.
startsWith
(
"http"
)){
handler_address
=
"http://"
+
handler_address
+
"/"
;
}
String
handler_name
=
jobDataMap
.
get
(
HandlerRepository
.
HANDLER_NAME
);
// trigger id, trigger time
Map
<
String
,
String
>
reqMap
=
new
HashMap
<
String
,
String
>();
reqMap
.
put
(
HandlerRepository
.
NAMESPACE
,
HandlerRepository
.
NameSpaceEnum
.
KILL
.
name
());
reqMap
.
put
(
HandlerRepository
.
HANDLER_NAME
,
handler_name
);
reqMap
.
put
(
HandlerRepository
.
TRIGGER_TIMESTAMP
,
String
.
valueOf
(
System
.
currentTimeMillis
()));
RemoteCallBack
callBack
=
HttpUtil
.
post
(
handler_address
,
reqMap
);
if
(
HttpUtil
.
RemoteCallBack
.
SUCCESS
.
equals
(
callBack
.
getStatus
()))
{
log
.
setHandleStatus
(
HttpUtil
.
RemoteCallBack
.
FAIL
);
log
.
setHandleMsg
(
"人为操作主动终止"
);
log
.
setHandleTime
(
new
Date
());
xxlJobLogDao
.
updateHandleInfo
(
log
);
return
new
ReturnT
<
String
>(
callBack
.
getMsg
());
}
else
{
return
new
ReturnT
<
String
>(
500
,
callBack
.
getMsg
());
}
}
}
xxl-job-admin/src/main/java/com/xxl/job/core/thread/JobMonitorHelper.java
浏览文件 @
39470eab
...
...
@@ -41,6 +41,11 @@ public class JobMonitorHelper {
XxlJobLog
log
=
DynamicSchedulerUtil
.
xxlJobLogDao
.
load
(
jobLogId
);
if
(
log
!=
null
)
{
if
(
RemoteCallBack
.
SUCCESS
.
equals
(
log
.
getTriggerStatus
())
&&
StringUtils
.
isBlank
(
log
.
getHandleStatus
()))
{
try
{
TimeUnit
.
SECONDS
.
sleep
(
10
);
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
JobMonitorHelper
.
monitor
(
jobLogId
);
}
if
(
RemoteCallBack
.
SUCCESS
.
equals
(
log
.
getTriggerStatus
())
&&
RemoteCallBack
.
SUCCESS
.
equals
(
log
.
getHandleStatus
()))
{
...
...
xxl-job-admin/src/main/java/com/xxl/job/service/job/RemoteHttpJobBean.java
浏览文件 @
39470eab
...
...
@@ -55,6 +55,7 @@ public class RemoteHttpJobBean extends QuartzJobBean {
// trigger request
HashMap
<
String
,
String
>
params
=
new
HashMap
<
String
,
String
>();
params
.
put
(
HandlerRepository
.
NAMESPACE
,
HandlerRepository
.
NameSpaceEnum
.
RUN
.
name
());
params
.
put
(
HandlerRepository
.
TRIGGER_LOG_URL
,
PropertiesUtil
.
getString
(
HandlerRepository
.
TRIGGER_LOG_URL
));
params
.
put
(
HandlerRepository
.
TRIGGER_LOG_ID
,
String
.
valueOf
(
jobLog
.
getId
()));
params
.
put
(
HandlerRepository
.
TRIGGER_TIMESTAMP
,
String
.
valueOf
(
System
.
currentTimeMillis
()));
...
...
xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobLogMapper.xml
浏览文件 @
39470eab
...
...
@@ -29,7 +29,7 @@
t.job_cron,
t.job_desc,
t.job_class,
t.job_d
esc
,
t.job_d
ata
,
t.trigger_time,
t.trigger_status,
t.trigger_msg,
...
...
xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/index.ftl
浏览文件 @
39470eab
...
...
@@ -67,8 +67,8 @@
<th
name=
"id"
>
id
</th>
<th
name=
"jobGroup"
>
任务组
</th>
<th
name=
"jobName"
>
任务名
</th>
<th
name=
"jobCron"
>
Cron
</th>
<th
name=
"jobDesc"
>
描述
</th>
<th
name=
"jobCron"
>
Cron
</th>
<th
name=
"jobClass"
>
JobBean
</th>
<th
name=
"jobData"
>
任务数据
</th>
<th
name=
"addTime"
>
新增时间
</th>
...
...
xxl-job-admin/src/main/webapp/WEB-INF/template/joblog/index.ftl
浏览文件 @
39470eab
...
...
@@ -83,6 +83,7 @@
<th
name=
"handleTime"
>
执行时间
</th>
<th
name=
"handleStatus"
>
执行结果
</th>
<th
name=
"handleMsg"
>
执行日志
</th>
<th
name=
"handleMsg"
>
操作
</th>
</tr>
</thead>
<tbody></tbody>
...
...
xxl-job-admin/src/main/webapp/WEB-INF/template/joblog/logdetail.ftl
0 → 100644
浏览文件 @
39470eab
<body style="color:white;background-color:black;" >
<pre>
<br>
<#if result.code == 200>${result.content}
<#else>${result.msg}</#if>
</pre>
</body>
xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js
浏览文件 @
39470eab
...
...
@@ -18,6 +18,7 @@ $(function() {
{
"data"
:
'id'
,
"bSortable"
:
false
,
"visible"
:
false
},
{
"data"
:
'jobGroup'
,
"visible"
:
false
,
"render"
:
function
(
data
,
type
,
row
)
{
var
groupMenu
=
$
(
"#jobGroup"
).
find
(
"option"
);
for
(
var
index
in
$
(
"#jobGroup"
).
find
(
"option"
))
{
...
...
@@ -29,14 +30,18 @@ $(function() {
}
},
{
"data"
:
'jobName'
},
{
"data"
:
'jobDesc'
,
"visible"
:
true
},
{
"data"
:
'jobCron'
,
"visible"
:
true
},
{
"data"
:
'jobDesc'
,
"visible"
:
false
},
{
"data"
:
'jobClass'
,
"visible"
:
true
},
{
"data"
:
'jobClass'
,
"visible"
:
false
},
{
"data"
:
'jobData'
,
"visible"
:
true
,
"render"
:
function
(
data
,
type
,
row
)
{
return
data
?
'<a class="logTips" href="javascript:;" >查看<span style="display:none;">'
+
data
+
'</span></a>'
:
"无"
;
var
_jobData
=
eval
(
'('
+
data
+
')'
);
// row.jobData
var
html
=
"<p title='"
+
data
+
"'>执行器:"
+
_jobData
.
handler_name
+
"<br>执行参数:"
+
_jobData
.
handler_params
+
"<br>执行机器:"
+
_jobData
.
handler_address
+
"</p>"
;
return
html
;
}
},
{
...
...
@@ -101,8 +106,8 @@ $(function() {
' handler_name="'
+
jobDataMap
.
handler_name
+
'" '
+
'>'
+
pause_resume
+
'<button class="btn btn-info btn-xs job_operate" type="job_trigger" type="button">执行</button>
'
+
'<button class="btn btn-warning btn-xs update" type="button">编辑</button><br>
'
+
'<button class="btn btn-info btn-xs job_operate" type="job_trigger" type="button">执行</button>'
+
'<button class="btn btn-warning btn-xs update" type="button">编辑</button><br>'
+
'<button class="btn btn-warning btn-xs" type="job_del" type="button" '
+
'onclick="javascript:window.open(
\'
'
+
logUrl
+
'
\'
)" >查看日志</button> '
+
'<button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button> '
+
...
...
@@ -140,12 +145,6 @@ $(function() {
}
});
// 日志弹框提示
$
(
'#job_list'
).
on
(
'click'
,
'.logTips'
,
function
(){
var
msg
=
$
(
this
).
find
(
'span'
).
html
();
ComAlertTec
.
show
(
msg
);
});
// 搜索按钮
$
(
'#searchBtn'
).
on
(
'click'
,
function
(){
jobTable
.
fnDraw
();
...
...
xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js
浏览文件 @
39470eab
...
...
@@ -48,6 +48,7 @@ $(function() {
{
"data"
:
'id'
,
"bSortable"
:
false
,
"visible"
:
false
},
{
"data"
:
'jobGroup'
,
"visible"
:
false
,
"bSortable"
:
false
,
"render"
:
function
(
data
,
type
,
row
)
{
var
groupMenu
=
$
(
"#jobGroup"
).
find
(
"option"
);
...
...
@@ -65,9 +66,14 @@ $(function() {
{
"data"
:
'jobClass'
,
"visible"
:
false
},
{
"data"
:
'jobData'
,
"visible"
:
fals
e
,
"visible"
:
tru
e
,
"render"
:
function
(
data
,
type
,
row
)
{
return
data
?
'<a class="logTips" href="javascript:;" >查看<span style="display:none;">'
+
data
+
'</span></a>'
:
"无"
;
var
_jobData
=
eval
(
'('
+
data
+
')'
);
// row.jobData
var
html
=
"<p title='"
+
data
+
"'>执行器:"
+
_jobData
.
handler_name
+
"<br>执行参数:"
+
_jobData
.
handler_params
+
"<br>执行机器:"
+
_jobData
.
handler_address
+
"</p>"
;
return
data
?
'<a class="logMsg" href="javascript:;" >查看<span style="display:none;">'
+
html
+
'</span></a>'
:
"无"
;
}
},
{
...
...
@@ -95,6 +101,27 @@ $(function() {
"render"
:
function
(
data
,
type
,
row
)
{
return
data
?
'<a class="logTips" href="javascript:;" >查看<span style="display:none;">'
+
data
+
'</span></a>'
:
"无"
;
}
},
{
"data"
:
'handleMsg'
,
"bSortable"
:
false
,
"render"
:
function
(
data
,
type
,
row
)
{
// better support expression or string, not function
return
function
()
{
// local job do not support trigger detail log, now
var
_jobData
=
eval
(
'('
+
row
.
jobData
+
')'
);
if
(
!
_jobData
.
handler_address
)
{
return
;
}
if
(
row
.
triggerStatus
==
'SUCCESS'
){
var
temp
=
'<a href="javascript:;" class="logDetail" _id="'
+
row
.
id
+
'">查看日志</a>'
;
if
(
!
row
.
handleStatus
){
temp
+=
'<br><a href="javascript:;" class="logKill" _id="'
+
row
.
id
+
'">终止任务</a>'
;
}
return
temp
;
}
return
null
;
}
}
}
],
"language"
:
{
...
...
@@ -123,17 +150,65 @@ $(function() {
}
});
// 任务数据
$
(
'#joblog_list'
).
on
(
'click'
,
'.logMsg'
,
function
(){
var
msg
=
$
(
this
).
find
(
'span'
).
html
();
ComAlert
.
show
(
2
,
msg
);
});
// 日志弹框提示
$
(
'#joblog_list'
).
on
(
'click'
,
'.logTips'
,
function
(){
var
msg
=
$
(
this
).
find
(
'span'
).
html
();
ComAlertTec
.
show
(
msg
);
});
// 搜索按钮
$
(
'#searchBtn'
).
on
(
'click'
,
function
(){
logTable
.
fnDraw
();
});
// 查看执行器详细执行日志
$
(
'#joblog_list'
).
on
(
'click'
,
'.logDetail'
,
function
(){
var
_id
=
$
(
this
).
attr
(
'_id'
);
window
.
open
(
base_url
+
'joblog/logDetailPage?id='
+
_id
);
return
;
/*
$.ajax({
type : 'POST',
url : base_url + 'joblog/logDetail',
data : {"id":_id},
dataType : "json",
success : function(data){
if (data.code == 200) {
ComAlertTec.show('<pre style="color: white;background-color: black;width2:'+ $(window).width()*2/3 +'px;" >'+ data.content +'</pre>');
} else {
ComAlertTec.show(data.msg);
}
},
});
*/
});
$
(
'#joblog_list'
).
on
(
'click'
,
'.logKill'
,
function
(){
var
_id
=
$
(
this
).
attr
(
'_id'
);
ComConfirm
.
show
(
"确认主动终止任务?"
,
function
(){
$
.
ajax
({
type
:
'POST'
,
url
:
base_url
+
'joblog/logKill'
,
data
:
{
"id"
:
_id
},
dataType
:
"json"
,
success
:
function
(
data
){
if
(
data
.
code
==
200
)
{
ComAlert
.
show
(
1
,
'操作成功'
);
logTable
.
fnDraw
();
}
else
{
ComAlert
.
show
(
2
,
data
.
msg
);
}
},
});
});
});
});
xxl-job-client-demo/src/main/java/com/xxl/job/service/handler/DemoJobHandler.java
浏览文件 @
39470eab
package
com
.
xxl
.
job
.
service
.
handler
;
import
java.util.Random
;
import
java.util.concurrent.TimeUnit
;
import
org.slf4j.Logger
;
...
...
@@ -25,7 +24,10 @@ public class DemoJobHandler extends IJobHandler {
@Override
public
JobHandleStatus
handle
(
String
...
params
)
throws
Exception
{
logger
.
info
(
" ... params:"
+
params
);
TimeUnit
.
SECONDS
.
sleep
(
new
Random
().
nextInt
(
5
));
for
(
int
i
=
0
;
i
<
60
;
i
++)
{
TimeUnit
.
SECONDS
.
sleep
(
1
);
logger
.
info
(
"handler run:{}"
,
i
);
}
return
JobHandleStatus
.
SUCCESS
;
}
...
...
xxl-job-client-demo/src/main/resources/log4j.properties
deleted
100644 → 0
浏览文件 @
ee9eca0d
log4j.rootLogger
=
info,console
log4j.appender.console
=
org.apache.log4j.ConsoleAppender
log4j.appender.console.layout
=
org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern
=
%d - xxl-job-client-demo - %p [%c] - <%m>%n
log4j.appender.logFile
=
org.apache.log4j.DailyRollingFileAppender
log4j.appender.logFile.File
=
${catalina.base}/logs/xxl-job-client-demo.log
log4j.appender.logFile.layout
=
org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern
=
%d - xxl-job-client-demo - %p [%c] - <%m>%n
xxl-job-client-demo/src/main/resources/log4j.xml
0 → 100644
浏览文件 @
39470eab
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd">
<log4j:configuration
xmlns:log4j=
"http://jakarta.apache.org/log4j/"
threshold=
"null"
debug=
"null"
>
<appender
name=
"CONSOLE"
class=
"org.apache.log4j.ConsoleAppender"
>
<param
name=
"Target"
value=
"System.out"
/>
<layout
class=
"org.apache.log4j.PatternLayout"
>
<param
name=
"ConversionPattern"
value=
"%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%t]-[%M]-[%L]-[%p] %m%n"
/>
</layout>
</appender>
<appender
name=
"ROOT"
class=
"org.apache.log4j.DailyRollingFileAppender"
>
<param
name=
"file"
value=
"/logs/xxl-job-client-demo.log"
/>
<param
name=
"append"
value=
"true"
/>
<param
name=
"encoding"
value=
"UTF-8"
/>
<layout
class=
"org.apache.log4j.PatternLayout"
>
<param
name=
"ConversionPattern"
value=
"%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%t]-[%M]-[%L]-[%p] %m%n"
/>
</layout>
</appender>
<appender
name=
"xxl-job"
class=
"com.xxl.job.client.log.XxlJobFileAppender"
>
<param
name=
"filePath"
value=
"/logs/xxl-job/"
/>
<param
name=
"append"
value=
"true"
/>
<param
name=
"encoding"
value=
"UTF-8"
/>
<layout
class=
"org.apache.log4j.PatternLayout"
>
<param
name=
"ConversionPattern"
value=
"%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%t]-[%M]-[%L]-[%p] %m%n"
/>
</layout>
</appender>
<logger
name=
"com.xxl.job.service.handler"
additivity=
"false"
>
<level
value=
"INFO"
/>
<appender-ref
ref=
"xxl-job"
/>
</logger>
<logger
name=
"com.xxl.job.client"
additivity=
"false"
>
<level
value=
"INFO"
/>
<appender-ref
ref=
"xxl-job"
/>
</logger>
<root>
<level
value=
"INFO"
/>
<appender-ref
ref=
"CONSOLE"
/>
<appender-ref
ref=
"ROOT"
/>
<appender-ref
ref=
"xxl-job"
/>
</root>
</log4j:configuration>
\ No newline at end of file
xxl-job-client/src/main/java/com/xxl/job/client/handler/HandlerRepository.java
浏览文件 @
39470eab
package
com
.
xxl
.
job
.
client
.
handler
;
import
java.util.Date
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
...
...
@@ -7,6 +8,7 @@ import org.slf4j.Logger;
import
org.slf4j.LoggerFactory
;
import
com.xxl.job.client.util.HttpUtil.RemoteCallBack
;
import
com.xxl.job.client.log.XxlJobFileAppender
;
import
com.xxl.job.client.util.JacksonUtil
;
/**
...
...
@@ -16,6 +18,9 @@ import com.xxl.job.client.util.JacksonUtil;
public
class
HandlerRepository
{
private
static
Logger
logger
=
LoggerFactory
.
getLogger
(
HandlerRepository
.
class
);
public
static
final
String
NAMESPACE
=
"namespace"
;
public
enum
NameSpaceEnum
{
RUN
,
KILL
,
LOG
}
public
static
final
String
HANDLER_ADDRESS
=
"handler_address"
;
public
static
final
String
HANDLER_NAME
=
"handler_name"
;
public
static
final
String
HANDLER_PARAMS
=
"handler_params"
;
...
...
@@ -35,36 +40,96 @@ public class HandlerRepository {
}
// handler push to queue
public
static
String
pushHandleQueu
e
(
Map
<
String
,
String
>
_param
)
{
logger
.
info
(
">>>>>>>>>>> xxl-job
pushHandleQueu
e start, _param:{}"
,
new
Object
[]{
_param
});
public
static
String
servic
e
(
Map
<
String
,
String
>
_param
)
{
logger
.
info
(
">>>>>>>>>>> xxl-job
servic
e start, _param:{}"
,
new
Object
[]{
_param
});
// callback
RemoteCallBack
callback
=
new
RemoteCallBack
();
callback
.
setStatus
(
RemoteCallBack
.
FAIL
);
//
encryption check
long
timestamp
=
_param
.
get
(
HandlerRepository
.
TRIGGER_TIMESTAMP
)!=
null
?
Long
.
valueOf
(
_param
.
get
(
HandlerRepository
.
TRIGGER_TIMESTAMP
)):-
1
;
if
(
System
.
currentTimeMillis
()
-
timestamp
>
6000
0
)
{
callback
.
setMsg
(
"
Timestamp check failed
."
);
//
check namespace
String
namespace
=
_param
.
get
(
HandlerRepository
.
NAMESPACE
)
;
if
(
namespace
==
null
||
namespace
.
trim
().
length
()==
0
)
{
callback
.
setMsg
(
"
param[NAMESPACE] can not be null
."
);
return
JacksonUtil
.
writeValueAsString
(
callback
);
}
// push data to queue
String
handler_name
=
_param
.
get
(
HandlerRepository
.
HANDLER_NAME
);
if
(
handler_name
!=
null
&&
handler_name
.
trim
().
length
()>
0
)
{
HandlerThread
handlerThread
=
handlerTreadMap
.
get
(
handler_name
);
if
(
handlerThread
!=
null
)
{
handlerThread
.
pushData
(
_param
);
callback
.
setStatus
(
RemoteCallBack
.
SUCCESS
);
}
else
{
callback
.
setMsg
(
"handler["
+
handler_name
+
"] not found."
);
// parse namespace
if
(
namespace
.
equals
(
HandlerRepository
.
NameSpaceEnum
.
RUN
.
name
()))
{
// encryption check
long
timestamp
=
_param
.
get
(
HandlerRepository
.
TRIGGER_TIMESTAMP
)!=
null
?
Long
.
valueOf
(
_param
.
get
(
HandlerRepository
.
TRIGGER_TIMESTAMP
)):-
1
;
if
(
System
.
currentTimeMillis
()
-
timestamp
>
60000
)
{
callback
.
setMsg
(
"Timestamp check failed."
);
return
JacksonUtil
.
writeValueAsString
(
callback
);
}
// push data to queue
String
handler_name
=
_param
.
get
(
HandlerRepository
.
HANDLER_NAME
);
if
(
handler_name
!=
null
&&
handler_name
.
trim
().
length
()>
0
)
{
HandlerThread
handlerThread
=
handlerTreadMap
.
get
(
handler_name
);
if
(
handlerThread
!=
null
)
{
handlerThread
.
pushData
(
_param
);
callback
.
setStatus
(
RemoteCallBack
.
SUCCESS
);
}
else
{
callback
.
setMsg
(
"handler["
+
handler_name
+
"] not found."
);
}
}
else
{
callback
.
setMsg
(
"param[HANDLER_NAME] can not be null."
);
}
}
else
if
(
namespace
.
equals
(
HandlerRepository
.
NameSpaceEnum
.
LOG
.
name
()))
{
String
trigger_log_id
=
_param
.
get
(
HandlerRepository
.
TRIGGER_LOG_ID
);
String
trigger_timestamp
=
_param
.
get
(
HandlerRepository
.
TRIGGER_TIMESTAMP
);
if
(
trigger_log_id
==
null
||
trigger_timestamp
==
null
)
{
callback
.
setMsg
(
"trigger_log_id | trigger_timestamp can not be null."
);
return
JacksonUtil
.
writeValueAsString
(
callback
);
}
}
else
{
callback
.
setMsg
(
"param[HANDLER_NAME] can not be null."
);
int
logId
=
-
1
;
Date
triggerDate
=
null
;
try
{
logId
=
Integer
.
valueOf
(
trigger_log_id
);
triggerDate
=
new
Date
(
Long
.
valueOf
(
trigger_timestamp
));
}
catch
(
Exception
e
)
{
}
if
(
logId
<=
0
||
triggerDate
==
null
)
{
callback
.
setMsg
(
"trigger_log_id | trigger_timestamp is not parsed valid."
);
return
JacksonUtil
.
writeValueAsString
(
callback
);
}
String
logConteng
=
XxlJobFileAppender
.
readLog
(
triggerDate
,
trigger_log_id
);
callback
.
setStatus
(
RemoteCallBack
.
SUCCESS
);
callback
.
setMsg
(
logConteng
);
}
else
if
(
namespace
.
equals
(
HandlerRepository
.
NameSpaceEnum
.
KILL
.
name
()))
{
// encryption check
long
timestamp
=
_param
.
get
(
HandlerRepository
.
TRIGGER_TIMESTAMP
)!=
null
?
Long
.
valueOf
(
_param
.
get
(
HandlerRepository
.
TRIGGER_TIMESTAMP
)):-
1
;
if
(
System
.
currentTimeMillis
()
-
timestamp
>
60000
)
{
callback
.
setMsg
(
"Timestamp check failed."
);
return
JacksonUtil
.
writeValueAsString
(
callback
);
}
// kill handlerThread, and create new one
String
handler_name
=
_param
.
get
(
HandlerRepository
.
HANDLER_NAME
);
if
(
handler_name
!=
null
&&
handler_name
.
trim
().
length
()>
0
)
{
HandlerThread
handlerThread
=
handlerTreadMap
.
get
(
handler_name
);
if
(
handlerThread
!=
null
)
{
IJobHandler
handler
=
handlerThread
.
getHandler
();
handlerThread
.
toStop
();
handlerThread
.
interrupt
();
regist
(
handler_name
,
handler
);
callback
.
setStatus
(
RemoteCallBack
.
SUCCESS
);
}
else
{
callback
.
setMsg
(
"handler["
+
handler_name
+
"] not found."
);
}
}
else
{
callback
.
setMsg
(
"param[HANDLER_NAME] can not be null."
);
}
}
else
{
callback
.
setMsg
(
"param[NAMESPACE] is not valid."
);
return
JacksonUtil
.
writeValueAsString
(
callback
);
}
logger
.
info
(
">>>>>>>>>>> xxl-job
pushHandleQueu
e end, triggerData:{}"
,
new
Object
[]{
callback
});
return
JacksonUtil
.
writeValueAsString
(
callback
);
logger
.
info
(
">>>>>>>>>>> xxl-job
servic
e end, triggerData:{}"
,
new
Object
[]{
callback
});
return
JacksonUtil
.
writeValueAsString
(
callback
);
}
}
xxl-job-client/src/main/java/com/xxl/job/client/handler/HandlerThread.java
浏览文件 @
39470eab
...
...
@@ -12,6 +12,7 @@ import org.slf4j.Logger;
import
org.slf4j.LoggerFactory
;
import
com.xxl.job.client.handler.IJobHandler.JobHandleStatus
;
import
com.xxl.job.client.log.XxlJobFileAppender
;
import
com.xxl.job.client.util.HttpUtil
;
import
com.xxl.job.client.util.HttpUtil.RemoteCallBack
;
...
...
@@ -25,6 +26,7 @@ public class HandlerThread extends Thread{
private
IJobHandler
handler
;
private
LinkedBlockingQueue
<
Map
<
String
,
String
>>
handlerDataQueue
;
private
ConcurrentHashSet
<
String
>
logIdSet
;
// avoid repeat trigger for the same TRIGGER_LOG_ID
private
boolean
toStop
=
false
;
public
HandlerThread
(
IJobHandler
handler
)
{
this
.
handler
=
handler
;
...
...
@@ -32,6 +34,18 @@ public class HandlerThread extends Thread{
logIdSet
=
new
ConcurrentHashSet
<
String
>();
}
public
IJobHandler
getHandler
()
{
return
handler
;
}
public
void
toStop
()
{
/**
* Thread.interrupt只支持终止线程的阻塞状态(wait、join、sleep),
* 在阻塞出抛出InterruptedException异常,但是并不会终止运行的线程本身;
* 所以需要注意,此处彻底销毁本线程,需要通过共享变量方式;
*/
this
.
toStop
=
true
;
}
public
void
pushData
(
Map
<
String
,
String
>
param
)
{
if
(
param
.
get
(
HandlerRepository
.
TRIGGER_LOG_ID
)!=
null
&&
!
logIdSet
.
contains
(
param
.
get
(
HandlerRepository
.
TRIGGER_LOG_ID
)))
{
handlerDataQueue
.
offer
(
param
);
...
...
@@ -41,7 +55,7 @@ public class HandlerThread extends Thread{
int
i
=
1
;
@Override
public
void
run
()
{
while
(
true
){
while
(
!
toStop
){
try
{
Map
<
String
,
String
>
handlerData
=
handlerDataQueue
.
poll
();
if
(
handlerData
!=
null
)
{
...
...
@@ -63,6 +77,7 @@ public class HandlerThread extends Thread{
JobHandleStatus
_status
=
JobHandleStatus
.
FAIL
;
String
_msg
=
null
;
try
{
XxlJobFileAppender
.
contextHolder
.
set
(
trigger_log_id
);
_status
=
handler
.
handle
(
handlerParams
);
}
catch
(
Exception
e
)
{
logger
.
info
(
"HandlerThread Exception:"
,
e
);
...
...
@@ -100,5 +115,6 @@ public class HandlerThread extends Thread{
logger
.
info
(
"HandlerThread Exception:"
,
e
);
}
}
logger
.
info
(
">>>>>>>>>>>> xxl-job handlerThrad stoped, hashCode:{}"
,
Thread
.
currentThread
());
}
}
xxl-job-client/src/main/java/com/xxl/job/client/log/XxlJobFileAppender.java
0 → 100644
浏览文件 @
39470eab
package
com
.
xxl
.
job
.
client
.
log
;
import
java.io.BufferedReader
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
import
org.apache.log4j.AppenderSkeleton
;
import
org.apache.log4j.Layout
;
import
org.apache.log4j.spi.LoggingEvent
;
/**
* store trigger log in each log-file
* @author xuxueli 2016-3-12 19:25:12
*/
public
class
XxlJobFileAppender
extends
AppenderSkeleton
{
// for HandlerThread
public
static
ThreadLocal
<
String
>
contextHolder
=
new
ThreadLocal
<
String
>();
public
static
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyyy-MM-dd"
);
// trogger log file path
public
static
volatile
String
filePath
;
public
void
setFilePath
(
String
filePath
)
{
XxlJobFileAppender
.
filePath
=
filePath
;
}
@Override
protected
void
append
(
LoggingEvent
event
)
{
String
trigger_log_id
=
contextHolder
.
get
();
if
(
trigger_log_id
==
null
||
trigger_log_id
.
trim
().
length
()==
0
)
{
return
;
}
// filePath/
File
filePathDir
=
new
File
(
filePath
);
if
(!
filePathDir
.
exists
())
{
filePathDir
.
mkdirs
();
}
// filePath/yyyy-MM-dd/
String
nowFormat
=
sdf
.
format
(
new
Date
());
File
filePathDateDir
=
new
File
(
filePathDir
,
nowFormat
);
if
(!
filePathDateDir
.
exists
())
{
filePathDateDir
.
mkdirs
();
}
// filePath/yyyy-MM-dd/9999.log
String
logFileName
=
trigger_log_id
.
concat
(
".log"
);
File
logFile
=
new
File
(
filePathDateDir
,
logFileName
);
if
(!
logFile
.
exists
())
{
try
{
logFile
.
createNewFile
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
return
;
}
}
// append file content
try
{
FileOutputStream
fos
=
null
;
try
{
fos
=
new
FileOutputStream
(
logFile
,
true
);
fos
.
write
(
layout
.
format
(
event
).
getBytes
(
"utf-8"
));
if
(
layout
.
ignoresThrowable
())
{
String
[]
throwableInfo
=
event
.
getThrowableStrRep
();
if
(
throwableInfo
!=
null
)
{
for
(
int
i
=
0
;
i
<
throwableInfo
.
length
;
i
++)
{
fos
.
write
(
throwableInfo
[
i
].
getBytes
(
"utf-8"
));
fos
.
write
(
Layout
.
LINE_SEP
.
getBytes
(
"utf-8"
));
}
}
}
fos
.
flush
();
}
finally
{
if
(
fos
!=
null
)
{
try
{
fos
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
@Override
public
void
close
()
{
// TODO Auto-generated method stub
}
@Override
public
boolean
requiresLayout
()
{
// TODO Auto-generated method stub
return
false
;
}
/**
* support read log-file
* @param triggerDate
* @param trigger_log_id
* @return
*/
public
static
String
readLog
(
Date
triggerDate
,
String
trigger_log_id
){
if
(
triggerDate
==
null
||
trigger_log_id
==
null
||
trigger_log_id
.
trim
().
length
()==
0
)
{
return
null
;
}
// filePath/
File
filePathDir
=
new
File
(
filePath
);
if
(!
filePathDir
.
exists
())
{
filePathDir
.
mkdirs
();
}
// filePath/yyyy-MM-dd/
String
nowFormat
=
sdf
.
format
(
triggerDate
);
File
filePathDateDir
=
new
File
(
filePathDir
,
nowFormat
);
if
(!
filePathDateDir
.
exists
())
{
filePathDateDir
.
mkdirs
();
}
// filePath/yyyy-MM-dd/9999.log
String
logFileName
=
trigger_log_id
.
concat
(
".log"
);
File
logFile
=
new
File
(
filePathDateDir
,
logFileName
);
if
(!
logFile
.
exists
())
{
try
{
logFile
.
createNewFile
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
return
null
;
}
}
try
{
InputStream
ins
=
null
;
BufferedReader
reader
=
null
;
try
{
ins
=
new
FileInputStream
(
logFile
);
reader
=
new
BufferedReader
(
new
InputStreamReader
(
ins
,
"utf-8"
));
if
(
reader
!=
null
)
{
String
content
=
null
;
StringBuilder
sb
=
new
StringBuilder
();
while
((
content
=
reader
.
readLine
())
!=
null
)
{
sb
.
append
(
content
).
append
(
"\n"
);
}
return
sb
.
toString
();
}
}
finally
{
if
(
ins
!=
null
)
{
try
{
ins
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
if
(
reader
!=
null
)
{
try
{
reader
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
}
xxl-job-client/src/main/java/com/xxl/job/client/netcom/jetty/XxlJobJettyServerHandler.java
浏览文件 @
39470eab
...
...
@@ -32,7 +32,7 @@ public class XxlJobJettyServerHandler extends AbstractHandler {
}
}
String
resp
=
HandlerRepository
.
pushHandleQueu
e
(
_param
);
String
resp
=
HandlerRepository
.
servic
e
(
_param
);
httpServletResponse
.
setContentType
(
"text/html;charset=utf-8"
);
httpServletResponse
.
setStatus
(
HttpServletResponse
.
SC_OK
);
...
...
xxl-job-client/src/main/java/com/xxl/job/client/netcom/servlet/XxlJobServlet.java
浏览文件 @
39470eab
...
...
@@ -44,7 +44,7 @@ public class XxlJobServlet extends HttpServlet {
}
}
String
resp
=
HandlerRepository
.
pushHandleQueu
e
(
_param
);
String
resp
=
HandlerRepository
.
servic
e
(
_param
);
response
.
getWriter
().
append
(
resp
);
return
;
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论