作者:竞霄

守时使命作为一种依照约守时刻履行预期逻辑的通用方法,在企业级开发中承载着丰厚的事务场景,比如后台守时同步数据生成报表,守时清理磁盘日志文件,守时扫描超时订单进行补偿回调等。程序开发人员在守时使命范畴有着许多结构和计划可供选择,并借此快速完成事务功用完成产品上线。本文将就当前干流守时使命处理计划进行介绍和剖析,希望能够在企业技能选型和项目架构重构时作为参考。

Crontab

方针定位

Crontab 作为 Linux 内置的可履行指令,能够完成依照 cron 表达式生成的时刻履行指定的体系指令或 shell 脚本。

运用办法

crontab 指令语法:

crontab [-u username] [-l | -e | -r ]
参数:
-u : 只有root用户才干进行这个使命,修改某个用户的crontab
-e : 修改 crontab 的工作内容
-l : 查阅 crontab 的工作内容
-r : 移除一切的 crontab 的工作内容

装备文件示例:

* * * * * touch ~/crontab_test
* 3 * * * ~/backup
0 */2 * * * /sbin/service httpd restart

完成原理

crond 守护进程是经过 Linux 启动时的 init 进程启动,由 cornd 每分钟会检查/etc/crontab 装备文件中是否有需求履行的使命,并经过 /var/log/cron 文件输出守时使命的履行情况。用户能够运用 Crontab 指令办理/etc/crontab 装备文件。

计划剖析

凭仗 Crontab 用户能够十分便当的快速完成简易的守时使命功用,但存在以下痛点:

  • 守时使命与指定 linux 机器绑定,当机器扩容或许替换时需求从头装备 contab,一起存在单点故障危险
  • 跟着守时使命规划增多,无一致视角对其进行使命进展的追寻和管控,难以保护
  • 功用过于简略,没有超时,重试,堵塞等使命高档特性
  • 可观测才能差,问题排查定位困难
  • 使命常驻,当无使命履行时形成不必要的资源本钱糟蹋

Spring Task

方针定位

Spring 结构供给了开箱即用的守时调度功用,用户能够经过 xml 或许@Scheduled 注解的办法标识指定办法履行的周期。Spring Task 支撑多种使命履行方法,包括带时区装备的 corn,固定延迟,固定速率等。

运用办法

代码实例如下:

@EnableScheduling
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}
@Component
public class MyTask {  
    @Scheduled(cron = "0 0 1 * * *")
    public void test() {
        System.out.println("test");  
    }  
}

完成原理

Spring Task 的原理是在初始化 bean 时凭仗 ScheduledAnnotationBeanPostProcessor 拦截@Scheduled 注解所标识的办法,并依据每个办法及其注解装备构建相应的 Task 实例注册到 ScheduledTaskRegistrar 中,并在单例 bean 初始化完成后经过 afterSingletonsInstantiated 回调设置 ScheduledTaskRegistrar 中的调度器 TaskScheduler,其底层依靠于 jdk 并发包中的 ScheduledThreadPoolExecutor 完成,并在 afterPropertiesSet 时将一切 Task 添加到 TaskScheduler 中调度履行。

计划剖析

凭仗 Spring Task 用户能够经过注解快速完成对指定办法的周期性履行,支撑多种周期性战略。但与 crontab 相似,相同有如下的痛点:

  • 默认为单线程履行,若前一个使命履行时刻较长会导致后续任饥饿堵塞,需求用户自行装备线程池
  • 各个节点独立运转,存在单点危险,无分布式和谐机制,要考虑制止并发履行
  • 跟着守时使命规划增多,无一致视角对其进行使命进展的追寻和管控,难以保护
  • 功用过于简略,没有超时,重试,堵塞等使命高档特性
  • 可观测才能差,问题排查定位困难
  • 使命常驻,当无使命履行时形成不必要的资源本钱糟蹋

ElasticJob

方针定位

ElasticJob 作为当当网开源的一款分布式使命结构,供给弹性调度,资源管控,作业办理等许多特性,其已经成为 Apache Shardingsphere 的子项目。ElasticJob 目前由 2 个相互独立的子项目 ElasticJob-Lite 和 ElasticJob-Cloud 组成,ElasticJob-Lite 定位为轻量级无中心化处理计划,运用 jar 的方法供给分布式使命的和谐服务;ElasticJob-Cloud 运用 Mesos 的处理计划,额定供给资源办理、运用分发以及进程阻隔等服务。一般运用 ElasticJob-Lite 即可满意需求。

运用办法

运用者需求在 yaml 中装备注册中心 zk 的地址以及使命的装备信息:

elasticjob:
  regCenter:
    serverLists: localhost:6181
    namespace: elasticjob-lite-springboot
  jobs:
    simpleJob:
      elasticJobClass: org.apache.shardingsphere.elasticjob.lite.example.job.SpringBootSimpleJob
      cron: 0/5 * * * * ?
      timeZone: GMT+08:00
      shardingTotalCount: 3
      shardingItemParameters: 0=Beijing,1=Shanghai,2=Guangzhou

完成对应的接口即可标识对应的使命,一起经过装备监听器来完成使命履行前后回调:

public class MyElasticJob implements SimpleJob {
    @Override
    public void execute(ShardingContext context) {
        switch (context.getShardingItem()) {
            case 0: 
                // do something by sharding item 0
                break;
            case 1: 
                // do something by sharding item 1
                break;
            case 2: 
                // do something by sharding item 2
                break;
            // case n: ...
        }
    }
}
public class MyJobListener implements ElasticJobListener {
    @Override
    public void beforeJobExecuted(ShardingContexts shardingContexts) {
        // do something ...
    }
    @Override
    public void afterJobExecuted(ShardingContexts shardingContexts) {
        // do something ...
    }
    @Override
    public String getType() {
        return "simpleJobListener";
    }
}

完成原理

ElasticJob 底层时刻调度基于 Quartz,Quartz 需求耐久化事务 Bean 到底层数据表中,体系侵入性相当严重,一起经过 db 锁进行使命抢占,不支撑并行调度,不具备可扩展性。而 ElasticJob 经过数据分片以及自定义分片参数的特性完成了水平扩展,能够将一个使命拆分为 N 个独立的使命项,由分布式的服务器并行履行各自分配到的分片项。比如一个数据库中有 1 亿条数据,需求将这些数据读取出来并进行计算,就能够将这 1 亿条数据划分红 10 个分片,每一个分片读取其间的 1 千万条数据,然后计算后写入数据库。如果有三台机器履行,A 机器分到分片(0,1,2,9),B 机器分到分片(3,4,5),C 机器分到分片(6,7,8),这也是比较于 Quartz 最显著的优势。

完成上 ElasticJob 运用 zookeeper 作为注册中心进行分布式调度和谐以及 leader 节点的推举,经过注册中心的暂时节点的变化来感知服务器的增减,每当 leader 节点推举,服务器上下线,分片总数改变时均会触发后续的从头分片,由 leader 节点在下次守时使命触发时进行具体的分片划分,再由各节点从注册中心中获取分片信息,作为使命的运转参数进行履行。

主流定时任务解决方案全横评

计划剖析

ElasticJob 作为分布式使命结构,处理了上述单节点使命无法确保使命履行过程中的高可用和高并发下履行的功用的问题,并支撑失败转移(failover)和错失履行的作业从头履行(misfire)等高档机制,但在运用过程中仍存在以下痛点:

  • 结构整体较重,需求依靠外置注册中心zk,增加了至少三台服务器的运用本钱和保护复杂度
  • 跟着使命量的不断增多,zk 作为有状况中间件将会成为功用瓶颈
  • 可观测才能弱,需求额定引入 db 并装备事情追寻
  • 使命常驻,当无使命履行时形成不必要的资源本钱糟蹋

XXLJob

方针定位

XXLJob 作为大众点评职工开源的一款分布式使命结构,其中心设计方针是开发迅速、学习简略、轻量级、易扩展。XXLJob 具备丰厚的功用,如使命分片广播,超时操控,失败重试,堵塞战略等,并经过体会友爱的白屏化操控台对使命进行办理和保护。

运用办法

XXLJob 分为中心式调度器和分布式履行器两部分组成,在运用时需求别离启动,在调度中心启动时需求装备所依靠的 db 装备。

履行器需求装备调度中心的地址:

xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
xxl.job.accessToken=
xxl.job.executor.appname=xxl-job-executor-sample
xxl.job.executor.address=
xxl.job.executor.ip=
xxl.job.executor.port=9999
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
xxl.job.executor.logretentiondays=30

经过 bean 方法办法方法创立使命和前后回调的运用办法如下:

@XxlJob(value = "demoJobHandler2", init = "init", destroy = "destroy")
public void demoJobHandler() throws Exception {
   int shardIndex = XxlJobHelper.getShardIndex();
   int shardTotal = XxlJobHelper.getShardTotal();
   XxlJobHelper.log("分片参数:当前分片序号 = {}, 总分片数 = {}", shardIndex, shardTotal);
}
public void init(){
        logger.info("init");
}
public void destroy(){
        logger.info("destory");
}

创立使命完成后,需求在操控台上装备使命的履行战略:

主流定时任务解决方案全横评

完成原理

XXLJob 完成大将调度体系与使命解耦,其自研调度器担任办理调度信息,依照调度装备宣布调度恳求,支撑可视化、简略且动态的办理调度信息,自动发现和路由,调度过期战略,重试战略,支撑履行器 Failover。履行器担任接纳调度恳求并履行使命逻辑,并接纳使命终止恳求和日志恳求,担任使命超时,堵塞战略等。调度器和履行器经过 restful api 进行通讯,调度器自身无状况支撑集群布置,提高调度体系容灾和可用性,经过 mysql 保护锁信息和耐久化。履行器无状况支撑集群布置,提高调度体系可用性,一起提高使命处理才能。

XXLJob 一次完好的使命调度通讯流程:首先调度中心向履行器内嵌 Server 发送 http 调度恳求,然后履行器履行对应的使命逻辑,待使命履行完成或超时后履行器发送 http 回调向调度中心返回调度成果。

主流定时任务解决方案全横评

计划剖析

XXLJob 在开源社区广泛盛行,凭仗其简略的操作和丰厚的功用已在多家公司投入运用,能够较好的满意生产级别的需求,但下面的一些痛点需求改善:

  • 需求依靠外置 DB,增加了数据库的运用本钱和保护复杂度
  • 依靠 DB 锁确保集群分布式调度的一致性,当短时使命量不断增多将对 db 形成较大压力,成为功用瓶颈
  • 相较于无中心方法需求额定布置调度器,调度器和履行器均需求常驻一起为确保高可用均至少两台,当无使命履行时形成不必要的资源本钱糟蹋

Serverless Job

方针定位

Serverless 作为云计算的最佳实践和未来演进趋势,其全保管免运维的运用体会和按量付费的本钱优势使得其在云原生年代备受推重。SAE (Serverless 运用引擎)Job 作为首款面向使命的 Serverless PaaS 平台,供给传统的用户体会。当前聚集支撑单机、广播、并行分片模型的使命,一起支撑事情驱动、并发战略和超时重试等许多特性,供给低本钱、多标准、高弹性的资源实例来满意短时使命的履行。

主流定时任务解决方案全横评

运用办法

关于运用上述一切计划的存量运用,SAE (Serverless 运用引擎) Job 在兼容功用体会的一起支撑零改造无感搬迁,无论用户运用的是 Crontab,Spring Task,仍是 ElasticJob, XXLJob,均可将代码包或许镜像直接布置到 SAE (Serverless 运用引擎) Job中,直接晋级成为 Serverless 架构, 然后立刻拥有 Serverless 所带来的技能上的优势,节省资源本钱和运维本钱。

关于运完即停的程序,无论是 Java,仍是 Shell,Python,Go,Php 均能够直接布置到 SAE (Serverless 运用引擎) Job 中, 然后立刻拥有白屏化管控,全保管免运维的完备体会以及开箱即用的可观测功用。

完成原理

SAE (Serverless 运用引擎)Job 底层为多租 Kubernetes,运用神龙裸金属安全容器、VK 对接 ECI 两种办法供给集群计算资源。用户在 SAE(Serverless 运用引擎)中运转的使命会映射到 Kubernetes 中相应的资源。其间多租才能是凭仗体系阻隔、数据阻隔、服务阻隔和网络阻隔完成租户间的阻隔。SAE (Serverless 运用引擎)Job 经过 Event Bridge 作为事情驱动源,在支撑丰厚调用办法的一起避免了 Kubernetes 内置守时器不确保按时触发以及精度时区上的问题。一起不断完善 Job 操控器的企业级特性,新增自定义分片,注入装备,差异化 GC,sidecar 自动退出,实时日志耐久化,事情通知等机制。并凭仗 Java 字节码增强技能接管使命调度,完成通用的 Java 方针结构的零改造 Serverless 化。运用 KubeVela 软件交付平台作为使命发布和办理的载体,以使命为中心,以开源开放的标准,经过声明式的办法完成整个云原生交付。SAE (Serverless 运用引擎)Job 将继续优化 etcd 以及调度器在短时使命高并发创立场景下的功率以及实例启动的极致弹功才能,结合弹性资源池确保使命调度的低延迟和高可用。

计划剖析

SAE (Serverless 运用引擎)Job 处理了上述守时使命处理计划的各种痛点,用户无需重视使命的调度和集群资源,无需布置的额定的运维依靠组件,也无需自建一整套监控告警体系,一起更重要的是无需云主机 7*24h 常驻,在低资源利用率的环境下继续耗费闲置资源。

SAE (Serverless 运用引擎)Job 相较于传统守时使命处理计划供给了三大中心价值:

  • 完备全保管:供给了一站式全保管的办理界面,其使命生命周期办理、可观测性开箱即用,用户能够低心智负担、零本钱地学习运用 SAE (Serverless 运用引擎)。
  • 简略免运维:屏蔽了底层资源,用户只需重视其中心的事务逻辑开发,无需操心集群可用性、容量、功用等方面的问题。
  • 超高性价比:采用按需运用、按量付费的方法,只有使命履行事务逻辑时才会拉起收费,其余时刻不收取任何费用,极大节省了资源的本钱开销。

总结

本文对干流守时使命处理计划(Crontab, Spring Task, ElasticJob, XXLJob, Serverless Job)的方针定位、运用办法、完成原理进行了阐述,一起就企业亲近重视的功用体会,功用本钱方面的问题进行横评剖析。最终希望大家选用 Serverless Job,感触其对传统使命所带来的新变革。

点击此处了解更多 SAE Job 的功用优势,和很多开源使命结构“低门槛”搬迁的计划!