热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

JavaElasticJob动态添加任务实现过程解析

这篇文章主要介绍了JavaElasticJob动态添加任务实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

背景

在使用Elastic-Job的过程中,有很多人遇到了这么一个问题,就是如何动态的去添加任务?

在官方的文档中也有对此作出回答,如下:

动态添加作业这个概念每个人理解不尽相同。

elastic-job-lite为jar包,由开发或运维人员负责启动。启动时自动向注册中心注册作业信息并进行分布式协调,因此并不需要手工在注册中心填写作业信息。 但注册中心与作业部署机无从属关系,注册中心并不能控制将单点的作业分发至其他作业机,也无法将远程服务器未启动的作业启动。elastic-job-lite并不会包含ssh免密管理等功能。

elastic-job-cloud为mesos框架,由mesos负责作业启动和分发。 但需要将作业打包上传,并调用elastic-job-cloud提供的REST API写入注册中心。 打包上传属于部署系统的范畴elastic-job-cloud并未涉及。

综上所述,elastic-job已做了基本动态添加功能,但无法做到真正意义的完全自动化添加。

接下来谈谈我对动态任务的理解,我眼中的动态任务分为2种:

一种是全新的任务,包括实现的逻辑也是全新的,也就是当我们的程序打成一个jar包后,线上已经在运行了,这个时候我加了一个新的任务,如何能做到不停服务,将这个任务集成到已有的任务中去,这个实现起来难度比较大,涉及到Java类的热加载等,不过最近阿里又有一开源大作JarsLink,GitHub地址:https://github.com/alibaba/jarslink,可以支持在运行时动态加载到系统中,实现不需要重启和发布系统新增功能。还有一种实现思路我们可以利用Groovy脚本来做这样的事情,一般情况下重启来发布新的任务会比较常见,如果各位一定要实现动态的任务可以自己尝试着去研究下我提供的思路。

另一种就是执行的业务逻辑不变,只是运行的时间发生变化。比如文章的定时发布,可以设置文章在某天的某分钟进行自动发布,实现这个功能有多种方式,你可以不停的扫描任务,一到时间点就自动发布,比较优雅的方式就是为每篇文章的自动发布都设置一个任务,通过Cron表达式来指定执行时间,不同的是每个任务都有自己的参数,业务逻辑都是固定的定时发布。
接下来我给大家介绍下Elastic-Job实现上面讲的第二种动态任务的方式,也就是任务的实现逻辑已经是存在的,只是需要发布成多个不同时间去触发的任务。

实战

实现任务的动态添加比较简单,只需要接收任务的信息,然后初始化一下就可以了,在实现的过程中笔者遇到了一个麻烦的问题?

在多节点分片任务却只有一个节点能执行,问题原因在于当有任务A和任务B,2个节点的时候,我们调用A节点的接口进行任务的动态添加,在A节点中初始化了任务调度器,数据也存储到了注册中心,但是B节点是不知道有新的任务添加,默认的使用方法是每个节点在启动时去初始化任务调度器,而我们的B节点已经启动过了,任务是新添加的。

解决这个问题最简单的方式就是将任务的节点都集中管理起来,无论动态任务在哪个节点上进行注册,都需要将这个请求转发到其他的节点上进行初始化操作,这样就可以保证多节点分片的任务正常执行。

还有一种对使用者更友好的办法是对Zookeeper中的节点进行监听,当有新的节点创建时,就自动获取这个节点的配置信息,在本地进行任务初始化,通过这样的方式就可以不用去转发请求到其他节点了,只要在任何节点有添加操作,都能被监听到,并自己去初始化。

监控代码如下:

/**
 * 开启任务监听,当有任务添加时,监听zk中的数据增加,自动在其他节点也初始化该任务
 */
public void monitorJobRegister() {
  CuratorFramework client = zookeeperRegistryCenter.getClient();
  @SuppressWarnings("resource")
  PathChildrenCache childrenCache = new PathChildrenCache(client, "/", true); 
  PathChildrenCacheListener childrenCacheListener = new PathChildrenCacheListener() { 
  public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception { 
    ChildData data = event.getData(); 
    switch (event.getType()) { 
        case CHILD_ADDED: 
          String cOnfig= new String(client.getData().forPath(data.getPath() + "/config"));
          Job job = JsonUtils.toBean(Job.class, config);
          addJob(job);
          break; 
        default: 
          break; 
    } 
   } 
 }; 
  childrenCache.getListenable().addListener(childrenCacheListener); 
  try { 
    childrenCache.start(StartMode.POST_INITIALIZED_EVENT);
  } catch (Exception e) {
    e.printStackTrace();
  } 
}

为了方便大家使用,我将动态添加任务的功能集成到了我之前的elastic-job-spring-boot-starter(https://github.com/yinjihuan/elastic-job-spring-boot-starter)中集成了动态添加的逻辑,大家引入依赖即可使用。

使用方式比较简单,只需要在启动类上加一个ComponentScan注解,让Spring能够扫描到elastic-job-spring-boot-starter提供的代码即可:

@SpringBootApplication
@EnableElasticJob
//开启动态任务添加API
@ComponentScan(basePackages = {"com.cxytiandi"})
public class JobApplication {
  public static void main(String[] args) {
    new SpringApplicationBuilder().sources(JobApplication.class).web(true).run(args);
    try {
      new CountDownLatch(1).await();
    } catch (InterruptedException e) {
    }
  }
}

配置好之后,启动项目就可以通过REST API来动态的注册任务,API列表如下:

/job
添加任务是POST请求,数据格式为JSON体提交,格式如下:
{
"jobName":"DynamicJob13",
"cron":"0 33 16 ?",
"jobType":"SIMPLE",
"jobClass":"com.cxytiandi.job.demo.DynamicJob",
"jobParameter":"2222222",
"shardingTotalCount":1
}

完整字段请参考:

https://github.com/yinjihuan/elastic-job-spring-boot-starter/blob/master/spring-boot-elastic-job-starter/src/main/java/com/cxytiandi/elasticjob/dynamic/bean/Job.java

注意:jobClass必须事先存在于服务中
* /job/remove

删除任务是GET请求,参数只要任务名称即可,比如:/job/remove?jobName=任务名。可以用于任务完成之后清空注册中心的任务信息。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • Docker安全策略与管理
    本文探讨了Docker的安全挑战、核心安全特性及其管理策略,旨在帮助读者深入理解Docker安全机制,并提供实用的安全管理建议。 ... [详细]
  • 调试利器SSH隧道
    在开发微信公众号或小程序的时候,由于微信平台规则的限制,部分接口需要通过线上域名才能正常访问。但我们一般都会在本地开发,因为这能快速的看到 ... [详细]
  • 精选10款Python框架助力并行与分布式机器学习
    随着神经网络模型的不断深化和复杂化,训练这些模型变得愈发具有挑战性,不仅需要处理大量的权重,还必须克服内存限制等问题。本文将介绍10款优秀的Python框架,帮助开发者高效地实现分布式和并行化的深度学习模型训练。 ... [详细]
  • 本文详细介绍了如何在 CentOS 7 及其衍生发行版(如 Red Hat, Oracle, Scientific Linux 7)上安装和完全卸载 GitLab。包括安装必要的依赖关系、配置防火墙、安装 GitLab 软件包以及常见问题的解决方法。 ... [详细]
  • 本文探讨了使用Python实现监控信息收集的方法,涵盖从基础的日志记录到复杂的系统运维解决方案,旨在帮助开发者和运维人员提升工作效率。 ... [详细]
  • 基于SSM框架的在线考试系统:随机组卷功能详解
    本文深入探讨了基于SSM(Spring, Spring MVC, MyBatis)框架构建的在线考试系统中,随机组卷功能的设计与实现方法。 ... [详细]
  • Python3爬虫入门:pyspider的基本使用[python爬虫入门]
    Python学习网有大量免费的Python入门教程,欢迎大家来学习。本文主要通过爬取去哪儿网的旅游攻略来给大家介绍pyspid ... [详细]
  • JavaScript 跨域解决方案详解
    本文详细介绍了JavaScript在不同域之间进行数据传输或通信的技术,包括使用JSONP、修改document.domain、利用window.name以及HTML5的postMessage方法等跨域解决方案。 ... [详细]
  • Requests库的基本使用方法
    本文介绍了Python中Requests库的基础用法,包括如何安装、GET和POST请求的实现、如何处理Cookies和Headers,以及如何解析JSON响应。相比urllib库,Requests库提供了更为简洁高效的接口来处理HTTP请求。 ... [详细]
  • 从理想主义者的内心深处萌发的技术信仰,推动了云原生技术在全球范围内的快速发展。本文将带你深入了解阿里巴巴在开源领域的贡献与成就。 ... [详细]
  • 本文详细介绍了如何正确设置Shadowsocks公共代理,包括调整超时设置、检查系统限制、防止滥用及遵守DMCA法规等关键步骤。 ... [详细]
  • 本文详细介绍了如何搭建一个高可用的MongoDB集群,包括环境准备、用户配置、目录创建、MongoDB安装、配置文件设置、集群组件部署等步骤。特别关注分片、读写分离及负载均衡的实现。 ... [详细]
  • 网络安全实验:Telnet与SSH服务对比及抓包分析
    本实验旨在对比Telnet和SSH两种安全通信协议的服务差异,并通过搭建服务器和使用Wireshark抓包工具进行详细分析。 ... [详细]
  • Spring Boot与Graylog集成实现微服务日志聚合与分析
    本文介绍了如何在Graylog中配置输入源,并详细说明了Spring Boot项目中集成Graylog的日志聚合和分析方法,包括logback.xml的多环境配置。 ... [详细]
author-avatar
薇洁诗婷梦添
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有