任务调度平台在服务器集群上的分布式搭建笔记

之前只在单点服务器上部署过任务调度平台,最近因为项目结题时计算速率的指标要求过高,计划采用多台服务器并发调度+各服务器上多线程并发相结合的形式提升效率,于是进行了任务调度平台的集群部署,最后计算效率提升了100倍。这里把搭建过程和相关的源码学习过程记录下来,便于其他同类需求项目的复现。

我这里的服务器集群为10台机架式服务器,有1个主控节点,9个计算节点,10台服务器的ip配置分别为192.168.1.101-192.168.1.110,任务调度平台基础框架沿袭之前项目使用的XXL-JOB,相关学习笔记可以参考作者之前的博文:
分布式任务调度平台XXL-JOB的Oracle版本搭建与学习笔记:
https://blog.csdn.net/nannan7777/article/details/107337464?spm=1001.2014.3001.5501
分布式任务调度平台XXL-JOB源码解析笔记
https://blog.csdn.net/nannan7777/article/details/117706213?spm=1001.2014.3001.5501

1 任务调度平台服务器集群搭建过程

首先XXL-JOB官网上给出的集群部署策略有两种,调度中心集群部署,以及执行器集群部署,具体要求如下:

(1) 调度中心集群部署

调度中心支持集群部署,提升调度系统容灾和可用性。
调度中心集群部署时,几点要求和建议:

1)DB配置保持一致;
2)集群机器时钟保持一致(单机集群忽视);
3)推荐通过Nginx反向代理为调度中心集群做负载均衡,分配域名。调度中心访问、执行器回调配置、调用API服务等操作均通过该域名进行。

(2) 执行器集群部署

执行器支持集群部署,提升调度系统可用性,同时提升任务处理能力。
执行器集群部署时,几点要求和建议:

1)执行器回调地址(xxl.job.admin.addresses)需要保持一致:执行器根据该配置进行执行器自动注册等操作;
2)同一个执行器集群内AppNamexxl.job.executor.appname)需要保持一致:调度中心根据该配置动态发现不同集群的在线执行器列表。

结合我自己工程项目的需求,这里采用执行器集群部署策略,将任务调度中心(xxl-job-admin)部署在主控节点的服务器上,并在全部服务器上部署执行器(xxl-job-executor),分别配置执行器地址为10台服务器的ip,同时这10个执行器的AppName保持一致,过程如下所示:

1)创建一个执行器集群:

(如果有多种类型的计算需求,可以创建多个执行器组,将计算任务按照类别分开,我这里仅有一类计算任务,因此只创建了一个执行器集群)

在这里插入图片描述
执行器集群的属性说明如下:
AppName:是每个执行器集群的唯一标示,执行器会周期性以AppName为对象进行自动注册。可通过该配置自动发现注册成功的执行器,供任务调度时使用。
名称:执行器的名称,因为AppName限制字母数字等组成,可读性不强,名称为了提高执行器的可读性。
排序:执行器的排序,系统中需要执行器的地方,如任务新增,将会按照该排序读取可用的执行器列表。
注册方式:调度中心获取执行器地址的方式:
自动注册:执行器自动进行执行器注册,调度中心通过底层注册表可以动态发现执行器机器地址。
手动录入:人工手动录入执行器的地址信息,多地址逗号分隔,供调度中心使用。
机器地址:"注册方式"为"手动录入"时有效,支持人工维护执行器的地址信息。

在这里插入图片描述
2)为各个执行器创建对应的服务器计算节点,并在各台服务器上部署执行器jar包,将全部执行器运行起来后计算节点状态会变为在线:

在这里插入图片描述
在这里插入图片描述
3)之后我修改了执行器集群的路由策略,代码里默认选择的是 RANDOM 随机策略,这里为均衡利用各个服务器的资源,我选择了ROUND 轮询策略:

  • 路由策略:
    FIRST(第一个):固定选择第一个机器;
    LAST(最后一个):固定选择最后一个机器;
    ROUND(轮询):顺序选择每一个机器;
    RANDOM(随机):随机选择在线的机器;
    CONSISTENT_HASH(一致性HASH):每个任务按照Hash算法固定选择某一台机器,且所有任务均匀散列在不同机器上。
    LEAST_FREQUENTLY_USED(最不经常使用):使用频率最低的机器优先被选举;
    LEAST_RECENTLY_USED(最近最久未使用):最久未使用的机器优先被选举;
    FAILOVER(故障转移):按照顺序依次进行心跳检测,第一个心跳检测成功的机器选定为目标执行器并发起调度;
    BUSYOVER(忙碌转移):按照顺序依次进行空闲检测,第一个空闲检测成功的机器选定为目标执行器并发起调度;
    SHARDING_BROADCAST (分片广播):广播触发对应集群中所有机器执行一次任务,同时系统自动传递分片参数;可根据分片参数开发分片任务;
    • 子任务:每个任务都拥有一个唯一的任务ID(任务ID可以从任务列表获取),当本任务执行结束并且执行成功时,将会触发子任务ID所对应的任务的一次主动调度。
    • 调度过期策略:
      • 忽略:调度过期后,忽略过期的任务,从当前时间开始重新计算下次触发时间;
      • 立即执行一次:调度过期后,立即执行一次,并从当前时间开始重新计算下次触发时间;
    • 阻塞处理策略:调度过于密集执行器来不及处理时的处理策略;
      单机串行(默认):调度请求进入单机执行器后,调度请求进入FIFO队列并以串行方式运行;
      丢弃后续调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,本次请求将会被丢弃并标记为失败;
      覆盖之前调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,将会终止运行中的调度任务并清空队列,然后运行本地调度任务;
    • 任务超时时间:支持自定义任务超时时间,任务运行超时将会主动中断任务;
    • 失败重试次数;支持自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试。

代码修改的部分如下所示:

private boolean saveJob(DagNode node, TaskDefinition definition) {
   
    Job jobInfo = new Job();
    jobInfo.setId(node.getId());
    jobInfo.setJobCron("* * * * * ?");
    jobInfo.setExecutorId(definition.getExecutor());
    jobInfo.setExecutorHandler(definition.getJobHandler());
    jobInfo.setGlueType(GlueTypeEnum.BEAN.name());
    jobInfo.setGlueRemark("NONE");
    jobInfo.setGlueUpdatetime(new Date());
    jobInfo.setExecutorFailRetryCount(ConstantUtils.EXECUTOR_FAIL_RETRY_COUNT);
    jobInfo.setExecutorTimeout(ConstantUtils.EXECUTOR_TIMEOUT);
    jobInfo.setAuthor("System Scheduler");
    jobInfo.setExecutorParam(node.getCommand());
    jobInfo.setJobDesc(node.getId());
    jobInfo.setAddTime(new Date());
    jobInfo.setUpdateTime(new Date());
    jobInfo.setExecutorRouteStrategy(ExecutorRouteStrategyEnum.ROUND.name());
    jobInfo.setExecutorBlockStrategy(ExecutorBlockStrategyEnum.SERIAL_EXECUTION.name());
    int res = ServerConfig.getInstance().getJobDao().save(jobInfo);
    if 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值