xxl-job日誌篇 - 騷操作

語言: CN / TW / HK

theme: cyanosis

“我報名參加金石計劃1期挑戰——瓜分10萬獎池,這是我的第n篇文章,點選檢視活動詳情

前言


在上一篇講了xxl-job二次開發後,我又將目光放到了它的日誌實現上,假設讓你去設計一個排程系統的日誌列印你會怎麼設計?

如果是我,我會把上下文一起響應到返回值,然後對響應值進行解碼,拿到業務列印的日誌,這是常規做法對吧,但是xxl就不是這樣做,所以我就蠻好奇它是咋實現的。

讓我們進去探個究竟吧~

image.png

xxl-job日誌列印方式


在舊版本採用XxlJobLogger.log,新版採用XxlJobHelper.log,然後我們管理後臺任務詳情就能看到我們列印的日誌了

XxlJobHelper

com.xxl.job.core.context.XxlJobHelper#log(java.lang.String, java.lang.Object...)

``` /* * append log with pattern * * @param appendLogPattern like "aaa {} bbb {} ccc" * @param appendLogArguments like "111, true" / public static boolean log(String appendLogPattern, Object ... appendLogArguments) {

FormattingTuple ft = MessageFormatter.arrayFormat(appendLogPattern, appendLogArguments);
String appendLog = ft.getMessage();

/*appendLog = appendLogPattern;
if (appendLogArguments!=null && appendLogArguments.length>0) {
    appendLog = MessageFormat.format(appendLogPattern, appendLogArguments);
}*/

StackTraceElement callInfo = new Throwable().getStackTrace()[1];
return logDetail(callInfo, appendLog);

} ```

FormattingTuple是組裝下列印的資料,將{}代替為後面引數,跟log.info一毛一樣。

new Throwable().getStackTrace()[1]這個是拿到當前執行方法的堆疊,如果有異常方便列印到具體的方法

com.xxl.job.core.context.XxlJobHelper#logDetail

image.png

好傢伙,他往日誌裡頭塞資料,也就是當你任務執行完的時候,XxlJobHelper列印的日誌會塞到特定的檔案裡頭,那麼他怎麼展示出來呢?

尋找xxl-job撈日誌的方法


好奇引發我百度了一下,發現它調了/logDetailCat這個方法去消費端取日誌,哈哈,常規操作,坐下~

image.png

撈日誌具體實現

``` @RequestMapping("/logDetailCat") @ResponseBody public ReturnT logDetailCat(String executorAddress, long triggerTime, long logId, int fromLineNum){ try { ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(executorAddress); ReturnT logResult = executorBiz.log(new LogParam(triggerTime, logId, fromLineNum));

  // is end
       if (logResult.getContent()!=null && logResult.getContent().getFromLineNum() > logResult.getContent().getToLineNum()) {
           XxlJobLog jobLog = xxlJobLogDao.load(logId);
           if (jobLog.getHandleCode() > 0) {
               logResult.getContent().setEnd(true);
           }
       }

  return logResult;

} catch (Exception e) { logger.error(e.getMessage(), e); return new ReturnT(ReturnT.FAIL_CODE, e.getMessage()); } } ``` com.xxl.job.admin.core.scheduler.XxlJobScheduler#getExecutorBiz

image.png

首先會去拿到當然執行地址的執行器,裡頭封裝了幾個方法:心跳、日誌、kill任務、執行任務

image.png

我們重點看下拉取日誌的實現方法:

com.xxl.job.core.biz.impl.ExecutorBizImpl#log

``` @Override public ReturnT log(LogParam logParam) { // log filename: logPath/yyyy-MM-dd/9999.log String logFileName = XxlJobFileAppender.makeLogFileName(new Date(logParam.getLogDateTim()), logParam.getLogId());

LogResult logResult = XxlJobFileAppender.readLog(logFileName, logParam.getFromLineNum());
return new ReturnT<LogResult>(logResult);

} ```

image.png

它會去拿我們剛剛存起來的日誌檔案,然後讀取出資料丟到xxl-job遠端介面,然後admin將jobid還有日誌記錄起來,到此就把定時任務的日誌收集起來~

思考環節


不得不說,操作有點騷,雖然可以實現日誌的非同步收集,也有一些弊端,比如說快取這些日誌是否有必要,讓我們一起來思考下:作者這麼做目的是什麼?

1、長定時任務列印一堆日誌?

A:我認為長任務就不應該出現,在我們上篇講xxl-job的任務排程實現用的是執行緒池,如果一些佔著也浪費資源。解決方案:採用非同步任務,機器後臺開個執行緒慢慢跑,這樣不會導致排程執行緒池爆滿,也不會說列印很多日誌需要採用這種方式來暫存。

那麼有人會反駁了,如果任務有問題怎麼中斷,所以我們需要另外實現任務中斷的方法,這也是很多小夥伴會遺忘的地方,導致有問題的時候,只能重啟去終止任務的執行

這樣也有好處,就是採用log.info,我們本身的日誌系統去收集日誌,統一在apm上檢視,不過這個有個坑是什麼呢,就是有些自研的apm在非同步的情況會丟失traceid,所以我們需要手動set進去!

image.png

好了,博主準備下班過國慶了~