ElasticJob 3.0.0-alpha 利用自定义JobErrorHandler实现错误重试

ElasticJob 3.0.0-alpha 自定义JobErrorHandler

起因

leader 要求任务调度得实现故障转移错误重试
令人尴尬的是,elasticJob只有失效转移,并没有错误重试。
不过xxljob可以进行失败错误:
在这里插入图片描述

这就真的很尴尬了 : )

有个解决方案,可以利用spring的重试机制,点这里查看详情

但我这倔脾气起来了,我特么就是不想引用包,就不能解决了??

然后就有了这篇文章,泪目,泪目!!!

正文

ElasticJobConfigurationProperties

先去属性配置类里面康康:

@Getter
@Setter
public class ElasticJobConfigurationProperties {

    private Class<? extends ElasticJob> elasticJobClass;

    private String elasticJobType;

    private String cron;
    
    private String jobBootstrapBeanName;

    private int shardingTotalCount;

    private String shardingItemParameters;

    private String jobParameter;

    private boolean monitorExecution;

    private boolean failover;

    private boolean misfire;

    private int maxTimeDiffSeconds = -1;

    private int reconcileIntervalMinutes;

    private String jobShardingStrategyType;

    private String jobExecutorServiceHandlerType;

    private String jobErrorHandlerType;

    private String description;

    private Properties props = new Properties();

    private boolean disabled;

    private boolean overwrite;

	public JobConfiguration toJobConfiguration(final String jobName) {......}
}

然后,你会惊讶的发现,真的很官网上说的一样,关于错误重试的字眼一点点都没有

柳暗花明又一村,可能是被上帝摸了摸头。在elasticJob的common包下,看见了异常处理handle的实现。
在这里插入图片描述
心跳有点止不住。。。。。。

随后在属性配置类中,找到了jobErrorHandlerType属性

内心的戏好像已经停不下来了。。。。。

思路:通过自定义JobErrorHandler,来达到错误重试效果

RetryJobErrorHandler

@Component
@Slf4j
public class RetryJobErrorHandler implements JobErrorHandler {

    private ElasticJobExecutor jobExecutor;

    private static int RETRY_TIME = 3;

    @Override
    public void handleException(String jobName, Throwable cause) {
        log.error(String.format("Job '%s' exception occur in job processing, start retry {}", jobName, RETRY_TIME), cause);
        if (RETRY_TIME == 0) {
            log.error(String.format("Job '%s' exception occur in job processing, retry still failure", jobName), cause);
            return;
        }
        jobExecutor.execute();
        RETRY_TIME--;
    }

    @Override
    public String getType() {
        return "Retry";
    }
}
    simpleJob-user:
      elasticJobClass: io.will.ejob.job.UserSimpleJob
      cron: 0/10 * * * * ?
      shardingTotalCount: 3
      overwrite: true
      jobErrorHandlerType: io.will.ejob.retry.RetryJobErrorHandler

写完自定义类,并在yaml中配置好类路径,已经止不住笑起来了

跑起来先:

Caused by: org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException: Can not find job error handler type 'io.will.ejob.retry.RetryJobErrorHandler'.
	at org.apache.shardingsphere.elasticjob.infra.handler.error.JobErrorHandlerFactory.getHandler(JobErrorHandlerFactory.java:56) ~[elasticjob-infra-common-3.0.0-alpha.jar:3.0.0-alpha]
	at org.apache.shardingsphere.elasticjob.executor.ElasticJobExecutor.<init>(ElasticJobExecutor.java:76) ~[elasticjob-executor-kernel-3.0.0-alpha.jar:3.0.0-alpha]
	at org.apache.shardingsphere.elasticjob.executor.ElasticJobExecutor.<init>(ElasticJobExecutor.java:63) ~[elasticjob-executor-kernel-3.0.0-alpha.jar:3.0.0-alpha]
	at org.apache.shardingsphere.elasticjob.lite.internal.schedule.JobScheduler.<init>(JobScheduler.java:86) ~[elasticjob-lite-core-3.0.0-alpha.jar:3.0.0-alpha]
	at org.apache.shardingsphere.elasticjob.lite.api.bootstrap.impl.ScheduleJobBootstrap.<init>(ScheduleJobBootstrap.java:43) ~[elasticjob-lite-core-3.0.0-alpha.jar:3.0.0-alpha]
	at org.apache.shardingsphere.elasticjob.lite.spring.boot.job.ElasticJobLiteAutoConfiguration.registerClassedJob(ElasticJobLiteAutoConfiguration.java:114) ~[elasticjob-lite-spring-boot-starter-3.0.0-alpha.jar:3.0.0-alpha]
	at org.apache.shardingsphere.elasticjob.lite.spring.boot.job.ElasticJobLiteAutoConfiguration.constructJobBootstraps(ElasticJobLiteAutoConfiguration.java:97) ~[elasticjob-lite-spring-boot-starter-3.0.0-alpha.jar:3.0.0-alpha]
	at org.apache.shardingsphere.elasticjob.lite.spring.boot.job.ElasticJobLiteAutoConfiguration.createJobBootstrapBeans(ElasticJobLiteAutoConfiguration.java:70) ~[elasticjob-lite-spring-boot-starter-3.0.0-alpha.jar:3.0.0-alpha]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_121]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_121]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	... 19 common frames omitted

我还是太年轻!!!

找问题

怎么会找不到呐,没有理由找不到啊,放容器里面了的啊

对比了下yaml配置类里的 elasticJobClass 和 jobErrorHandlerType

嗯??? class??type??莫非不是写类路径??

再进入ElasticJobConfigurationProperties 类中康康:

......
private Class<? extends ElasticJob> elasticJobClass;
......
private String jobErrorHandlerType;
......

是咯!!!一个是类,一个是String,肯定找不到

    simpleJob-user:
      elasticJobClass: io.will.ejob.job.UserSimpleJob
      cron: 0/10 * * * * ?
      shardingTotalCount: 3
      overwrite: true
      jobErrorHandlerType: Retry

好像看见了胜利的手,再向我招来!!!

Caused by: org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException: Can not find job error handler type 'Retry'.
	at org.apache.shardingsphere.elasticjob.infra.handler.error.JobErrorHandlerFactory.getHandler(JobErrorHandlerFactory.java:56) ~[elasticjob-infra-common-3.0.0-alpha.jar:3.0.0-alpha]
	at org.apache.shardingsphere.elasticjob.executor.ElasticJobExecutor.<init>(ElasticJobExecutor.java:76) ~[elasticjob-executor-kernel-3.0.0-alpha.jar:3.0.0-alpha]
	at org.apache.shardingsphere.elasticjob.executor.ElasticJobExecutor.<init>(ElasticJobExecutor.java:63) ~
	......

傻眼了!!!还是不可以!!!

Debug

事到如今,也只剩下Debug,进去康康到底发生了什么。。。泪目!!!

在这里插入图片描述
嗯嗯能够拿到Type,再进去康康

在这里插入图片描述
找到原因了:是在类加载时候,自定义JobErrorHandler走远了

我好像有点肝不动了 !!!

解决方法

  1. 反射

直接上代码:

static {
        try {
            HashMap<String, JobErrorHandler> stringJobErrorHandlerHashMap = new LinkedHashMap<>();
            RetryJobErrorHandler retryJobErrorHandler = new RetryJobErrorHandler();
            stringJobErrorHandlerHashMap.put("Retry", retryJobErrorHandler);

            Class<?> factoryClass = Class.forName("org.apache.shardingsphere.elasticjob.infra.handler.error.JobErrorHandlerFactory");

            Field[] fields = factoryClass.getDeclaredFields();
            Field handlers = null;
            for (int i = 0; i < fields.length; i ++) {
                fields[i].setAccessible(true);
                System.out.println(fields[i].getName());
                if (fields[i].getName().equals("HANDLERS")) {
                    handlers = fields[i];
                }
            }
            int modify = handlers.getModifiers();

            handlers.setAccessible(true);
            Field modifiersField = Field.class.getDeclaredField("modifiers");
            modifiersField.setAccessible(true);

            // 修改权限
            modify = handlers.getModifiers() & ~Modifier.FINAL;
            //更改目标对象的修饰符
            modifiersField.setInt(handlers, modify);

            handlers.set(null, stringJobErrorHandlerHashMap);
            System.out.println(handlers);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

看截图:
在这里插入图片描述

  1. Java configuration

人家大佬是这么说的:
在这里插入图片描述

使用配置类:

// 待更新
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值