xxl-job使用笔记


定时任务的实现方式不只一种。
最基础的是spring的@Scheduled定时任务,使用简单方便,但是用的多了,有一些确定。

因为一般集群都带了xxl-job-admin微服务,这里只说如何集成。

xxl-job

我们常说的xxjob全称是xxl-job,之所以读xxjob,就是为了易读。

maven依赖:

<dependency>
	<groupId>com.xuxueli</groupId>
	<artifactId>xxl-job-core</artifactId>
	<version>2.3.0</version>
</dependency>

配置文件新增

xxl:
  job:
    admin:
      # 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
      addresses: http://192.168.0.1/xxl-job-admin
    # 执行器通讯TOKEN [选填]:非空时启用;
    accessToken: default_token
    executor:
      # 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
      appname: xxl-job-test
      address:
      # 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
      ip:
      # 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
      port: 9997
      # 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
      logpath: /data/logs/xxl-job/jobhandler
      # 执行器日志保存天数 [选填] :值大于3时生效,启用执行器Log文件定期清理功能,否则不生效;
      logretentiondays: 7

XxlJobConfig类

直接从git项目复制过来一份。

@Configuration
public class XxlJobConfig {
    private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);

    @Value("${xxl.job.admin.addresses}")
    private String adminAddresses;

    @Value("${xxl.job.accessToken}")
    private String accessToken;

    @Value("${xxl.job.executor.appname}")
    private String appname;

    @Value("${xxl.job.executor.address}")
    private String address;

    @Value("${xxl.job.executor.ip}")
    private String ip;

    @Value("${xxl.job.executor.port}")
    private int port;

    @Value("${xxl.job.executor.logpath}")
    private String logPath;

    @Value("${xxl.job.executor.logretentiondays}")
    private int logRetentionDays;


    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() {
        logger.info(">>>>>>>>>>> xxl-job config init.");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        xxlJobSpringExecutor.setAppname(appname);
        xxlJobSpringExecutor.setAddress(address);
        xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(port);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setLogPath(logPath);
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);

        return xxlJobSpringExecutor;
    }
}

JobHandler例子

代码:

@Slf4j
@Component
public class EntranceJobHandler {

    @XxlJob("demoJobHandler")
    public void demoJobHandler() throws Exception {
        System.out.println("XXL-JOB Hello World");
        // 获取参数
        String param = XxlJobHelper.getJobParam();
        log.info("接收调度中心参数:\n{}", param);

        // 控制台输出日志
        log.info("myXxlJobHandler execute...");

        try {
            //书写业务逻辑
            // TODO-MICHAEL: 2018/10/25

            // 写日志到调度中心日志中
            XxlJobHelper.log("myXxlJobHandler execute Success...");
            // 设置任务结果
            XxlJobHelper.handleSuccess();
        } catch (Exception e) {
            log.error("myXxlJobHandler execute Fail ...", e);
            //写日志到调度中心日志中
            XxlJobHelper.log("myXxlJobHandler execute Fail...");
            // 设置任务结果
            XxlJobHelper.handleFail();
        }
    }
}

然后启动项目即可。

xxl-job机制

先有个xxl-job-admin服务,即调度中心。(需要数据库支持)
其他微服务可以注册到这个调度中心。
每个微服务可以看做一个执行器,执行器的名字要和admin界面维护的一致。
每个执行器可以有多个任务,任务的名字要和jobHandler一致。
然后在界面可以做各种操作。

xxl-job-admin配置

1、新增执行器(执行器可以理解为就是微服务)。
2、新增任务(一个执行器可以有多个任务),点立即执行,再点查看日志就可以看效果。

@XxlJob 和 @JobHandler(过时了)

问: 为什么找不到@JobHandler了?
很简单,他过时了,最新的注解是 @XxlJob。

我们看下JobHandler的源码就一目了然:

// * will be replaced by {@link com.xxl.job.core.handler.annotation.XxlJob}
// *
// * @author 2016-5-17 21:06:49
// */
//@Target({ElementType.TYPE})
//@Retention(RetentionPolicy.RUNTIME)
//@Inherited
//@Deprecated
//public @interface JobHandler {
//
//    String value();
//
//}

对,你没看错,都被注释掉了,关键的还有一句
will be replaced by {@link com.xxl.job.core.handler.annotation.XxlJob}
已经被@XxlJob替代了。

其他

报错 msg:job handler [demoJobHandler] not found.

这个问题有多重因素,要逐个排查。
1、执行器地址对不对。
2、jobHandler的名称对不对。
3、jobConfig是否加载。
4、jobHandler是否加载。

XxlJobConfig 确认是否加载
发现果然没有加载,这个是启动的时候就加载。

@XxlJob(“demoJobHandler”) 所在类是否加载
实际上也没有加载,这个是使用的时候加载,所以方法里的日志不会直接打出来。

Application的package及子package的类会自动加载,否则不会加载。
调整下未加载类到Application的package及子package即可。
另外一种思路:
Application放到高层级的目录,例如直接放到com目录下。

xxl-job报错 xxl-job registry fail, registryParam:RegistryParam{registryGroup=‘EXECUTOR’, registryKey=‘xxl-job-invoice-api’, registryValue=‘http://xxxxxx:9990/’}, registryResult:ReturnT [code=500, msg=The access token is wrong., content=null]

注册报错,一般是配置问题。
例如这里就是access token错了。
当然其他情况也可能是ip地址错了,看具体报错吧。

git地址

码云的git地址(实测可用):
https://gitee.com/xuxueli0323/xxl-job

这里面有源码,包括示例等。

xxl-job-admin的密码在哪里设置的呢

默认是在代码里面写死了,直接用就可以。

public class JobInfoControllerTest extends AbstractSpringMvcTest {
  private static Logger logger = LoggerFactory.getLogger(JobInfoControllerTest.class);

  private Cookie cookie;

  @BeforeEach
  public void login() throws Exception {
    MvcResult ret = mockMvc.perform(
        post("/login")
            .contentType(MediaType.APPLICATION_FORM_URLENCODED)
            .param("userName", "admin")
            .param("password", "123456")
    ).andReturn();
    cookie = ret.getResponse().getCookie(LoginService.LOGIN_IDENTITY_KEY);
  }
}