xxl-job执行器在k8s中丢失日志问题和xxl日志读写原理

​   ​   最近公司的中台项目要使用 xxl-job做元数据采集,etl读取,数据加工等。但是遇到容器中日志丢失问题,本文章会主要分享两部分内容

​  ​   1 xxl-job日志读写原理

​  ​   2 日志丢失的解决思路



​  ​  Xxl-job 日志读写原理:

​  ​  版本:xxl-job-2.3.0


​  ​  一 xxl-job 写日志原理

​   ​   Xxl-job写日志是在 执行器中执行的,核心类是 xxl-job-core 中的com.xxl.job.core.log.XxlJobFileAppender 类。

​   ​   1 主要逻辑是,执行器会先从xxl-admin获取日志id,这个id是数据库中log表的自增长id

​   ​   2 将内容写到以上述获取到的log id为名的日志文件中

​   ​   注意: 因为文件名既是数据库自增长ID,所以文件名在并发环境中也不会重复



​  ​   二 xxl-job 读日志原理

​   ​   xxl-job的读日志主要逻辑,前端发起读取日志,会经过以下两步

​   ​   1 先会调用 JobLogController 的logDetailPage ,返回日志详情页面

​   ​   2 然后日志详情页面会不断轮询JobLogController 的 logDetailCat 接口,获取日志内容



​   ​   logDetailCat 接口获取日志内容的主要逻辑是

​   ​   1 根据logid获取执行器的IP 地址

​   ​   2 使用netty通信,发送命令给执行器,读取日志



​  ​   Xxl-job执行器,在k8s中日志丢失问题以及解决。

  ​   一 丢失原因是

  ​  1 容器中不持久化执行器的日志文件
  ​  2 k8s ip不固定



​  ​   二 解决方法

​   ​   其实解决很简单,我们一步步来解决久可以了

​   ​   1 首先是 容器中不持久化日志文件,我们可以在容器中挂载网络存储,最简单的比如是nfs

​   ​   2 k8s ip不固定,那么我们就不使用 netty 通信,通知执行器读取文件了,我们直接在xxl-job-admin读取即可,即xxl-job-admin直接读取日志文件,其实也很简单,只需要把JobLogController 的 logDetailCat 接口 中的ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(executorAddress); 改成 ExecutorBiz executorBiz = new ExecutorBizImpl(); 即可


​ ​  ​  具体代码如下

@RequestMapping("/logDetailCat")
@ResponseBody
public ReturnT<LogResult> logDetailCat(String executorAddress, long triggerTime, long logId, int fromLineNum){
   try {
   // ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(executorAddress);
      ExecutorBiz executorBiz = new ExecutorBizImpl();

      ReturnT<LogResult> 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<LogResult>(ReturnT.FAIL_CODE, e.getMessage());
   }
}



​   ​   注意:本文章只是提供一个思路,并未在生产大规模使用。

你可能感兴趣的:(数据中台,java)