工作笔记(五十六)— xxl-job
xxl-job是一个专门用于处理分布式定时任务的高效任务调度框架,它由调度中心和执行器两个核心组件构成。码分调度中心作为可视化管理平台,码分负责管理和发出调度请求,码分管理调度信息;而执行器则负责接收这些请求并执行相应的码分任务逻辑。
要使用xxl-job,码分aot模式源码首先进行安装和配置。码分从源码开始,码分解压后初始化数据库,码分并运行提供的码分SQL脚本创建相关表。调度中心配置主要包括配置文件设置,码分它是码分一个基于springBoot的项目,通过jar包启动。码分部署时,码分保持数据库配置一致性以及机器时钟同步至关重要。码分访问调度中心的默认地址是/googlearchive/android-JobScheduler
JobScheduleræ¯ä¸ä¸ªæ½è±¡ç±»ï¼å®å¨ç³»ç»æ¡æ¶çå®ç°ç±»æ¯android.app.JobSchedulerImpl
æ§è¡çå ¥å£æ¯JobScheduler.schedulerï¼å ¶å®æ¯è°äºJobSchedulerImplä¸çscheduleæ¹æ³ï¼ç¶ååè°äºmBinder.schedule(job)ãè¿ä¸ªmBinderå°±æ¯JobSchedulerServiceï¼éè¿Binderè·¨è¿ç¨è°ç¨JobSchedulerServiceã
æåè°ç¨å°JobSchedulerServiceä¸çscheduleæ¹æ³:
æ¥çåéMSG_CHECK_JOBæ¶æ¯ï¼æ¶æ¯å¤ççå°æ¹æ¯
æ¥çæ§è¡JobHandlerä¸ç maybeRunPendingJobsH æ¹æ³ï¼å¤çç¸åºçä»»å¡
availableContextæ¯JobServiceContextï¼å³ServiceConnectionï¼è¿ä¸ªæ¯è¿ç¨é´é讯ServiceConnectionï¼éè¿è°ç¨availableContext.executeRunnableJob(nextPending)æ¹æ³ï¼ä¼è§¦åè°ç¨onServiceConnectedï¼çå°è¿éåºè¯¥æç½äºï¼onServiceConnectedæ¹æ³ä¸çserviceå°±æ¯Jobserviceï¼éé¢è¿ç¨äºWakeLockéï¼é²æ¢ææºä¼ç ã
æ¥çï¼éè¿Handleråæ¶æ¯ï¼è°ç¨äºhandleServiceBoundH()æ¹æ³ã
ä»ä¸é¢æºç å¯ä»¥çåºï¼æç»æ¯è§¦åè°ç¨äºJobServiceä¸çstartJobæ¹æ³ã
ä»æºç çï¼è®¾ç½®çå 容åºç¨äº JobStatus ï¼ä¾å¦ç½ç»éå¶
èå¨JobSchedulerServiceç±»ï¼ç¸å ³çç¶ææ§å¶å¨å ¶æé å½æ°é:
ä¾å¦ç½ç»æ§å¶ç±»ConnectivityControllerç±»
å½ç½ç»åçæ¹åæ¶ï¼ä¼è°ç¨updateTrackedJobs(userid)æ¹æ³ï¼å¨updateTrackedJobsæ¹æ³ä¸ï¼ä¼å¤æç½ç»æ¯å¦ææ¹åï¼ææ¹åçä¼è°mStateChangedListener.onControllerStateChanged()æ¹æ³ï¼ç¶åè°ç¨äºJobSchedulerServiceç±»ä¸onControllerStateChangedæ¹æ³ï¼
æ¥çä¹æ¯å¤çMSG_CHECK_JOB æ¶æ¯ï¼åä¸æä¸æ ·ï¼æç»è§¦åè°ç¨äºJobServiceä¸çstartJobæ¹æ³ã
JobSchedulerServiceæ¯ä¸ä¸ªç³»ç»æå¡ï¼å³åºè¯¥å¨SystemServerå¯å¨çãé 读SystemServerçæºç ï¼
run æ¹æ³å¦ä¸ï¼
æ¥çç startOtherServices()
å æ¤ï¼å¨è¿éå°±å¯å¨äºJobSchedulerServiceæå¡ã
1. android æ§è½ä¼åJobScheduler使ç¨åæºç åæ
2. Android 9.0 JobScheduler(ä¸) JobSchedulerç使ç¨
3. Android 9.0 JobScheduler(äº) JobScheduleræ¡æ¶ç»æç®è¿°åJobSchedulerServiceçå¯å¨
4. Android 9.0 JobScheduler(ä¸) ä»Jobçå建å°æ§è¡
5. Android 9.0 JobScheduler(å) Job约ææ¡ä»¶çæ§å¶
6. ç解JobScheduleræºå¶
Xxl-Job中的概念和使用详解
一、调度中心
调度中心是独立的Web服务,专门用于触发定时任务执行。它提供管理界面,方便用户配置和控制定时任务的执行逻辑。调度中心依赖数据库存储数据,并支持集群模式,但集群内各实例间无直接通信,数据共享通过数据库实现。
二、执行器
执行器是执行具体任务的实体,与服务实例一一对应。每个执行器有自己的命名,通常推荐以服务名命名,以方便识别。
三、宝嗒线源码任务
任务就是定时执行的逻辑,一个执行器可以包含多个任务。调度中心负责管理任务的触发逻辑,执行器则负责实际执行任务。
创建调度中心与执行器:
1. 下载调度中心源码,调整数据库连接信息,执行指定的SQL脚本文件。
2. 启动调度中心,可以打包成jar或直接运行,访问指定URL即可访问控制台。
3. 添加执行器与任务:设置执行器名字,指定任务名称和选择任务执行模式。
实现步骤:
1. 引入依赖,配置XxlJobSpringExecutor,并在服务中使用@XxlJob注解定义任务。
2. 任务执行:通过反射或动态修改代码实现任务逻辑,配置执行器与任务。
核心原理:
执行器启动时执行初始化操作,包括JobHandler初始化,创建Http服务器和注册到调度中心。JobHandler封装定时任务,负责执行任务。调度中心会计算任务触发时机,通过查询数据库获取任务信息,并按照预读时间决定执行哪些任务。
任务触发流程:
1. 调度中心启动后,开启调度线程,查询并调度任务执行。
2. 调度线程将任务提交到线程池执行。
3. 执行器根据路由策略选择执行器实例,电脑刷枪源码执行任务并返回结果给调度中心。
优化与路由策略:
1. 使用线程池异步执行任务触发,避免阻塞调度效率。
2. 实现快慢线程池,优化任务触发时间较长的任务处理。
3. 路由策略多样,包括分片广播、一致性Hash、LRU等,确保任务均衡分配。
执行与结果回调:
执行器创建单独线程执行任务,并将结果异步回调给调度中心。至此,任务执行过程完成。
总结:
通过调度中心和执行器协同工作,实现灵活的定时任务管理。核心原理包括初始化、任务调度、路由选择以及执行结果回调,通过优化策略保证任务高效执行。Xxl-Job提供丰富功能和灵活配置,适用于各类定时任务场景。
JobIntentService源码解析
Android 8.0引入了更严格的系统资源管控,包括后台限制规则。
在Android 8.0中,禁止应用在后台运行时创建Service。
若应用在后台运行,将会收到错误提示。
JobIntentService是Android 8.0中新增的类,继承自Service。贷款平台php源码
该类用于执行加入队列的任务。对于Android 8.0及以上系统,JobIntentService任务将通过JobScheduler.enqueue执行,而8.0以下系统则继续使用Context.startService。
JobIntentService使用便捷,只需调用YourService.enqueueWork(context, new Intent())方法。
相较于JobService,JobIntentService简化了操作,开发者无需关注其生命周期,避免了在后台运行时创建Service导致的crash问题,且通过静态方法即可启动。
源码解析如下:首先记录几个关键变量的含义。
在Android 8.0以上的系统中,执行流程如下。
work的具体逻辑处理在何处?
通过JobService的工作原理,查找onStartJob方法。
最终,处理work的逻辑会流转至AsyncTask中,通过protected abstract void onHandleWork(@NonNull Intent intent)方法实现。
子类需实现jobIntentService处理work,使用线程池的AsyncTask执行,无需考虑主线程阻塞问题。
针对Android 8.0以下系统,流程如下:回到onStartCommand方法。
同样,最终会流转至Asynctask任务执行onHandleWork。
技术人生阅读源码——Quartz源码分析之任务的调度和执行
Quartz源码分析:任务调度与执行剖析
Quartz的调度器实例化时启动了调度线程QuartzSchedulerThread,它负责触发到达指定时间的任务。该线程通过`run`方法实现调度流程,包含三个主要阶段:获取到达触发时间的88福利源码triggers、触发triggers、执行triggers对应的jobs。
获取到达触发时间的triggers阶段,通过`JobStore`接口的`acquireNextTriggers`方法获取,由`RAMJobStore`实现具体逻辑。触发triggers阶段,调用`triggersFired`方法通知`JobStore`触发triggers,处理包括更新trigger状态与保存触发过程相关数据等操作。执行triggers对应jobs阶段,真正执行job任务,先构造job执行环境,然后在子线程中执行job。
job执行环境通过`JobRunShell`提供,确保安全执行job,捕获异常,并在任务完成后根据`completion code`更新trigger。job执行环境包含job对象、trigger对象、触发时间、上一次触发时间与下一次触发时间等数据。Quartz通过线程池提供多线程服务,使用`SimpleThreadPool`实例化`WorkerThread`来执行job任务,最终调用`Job`的`execute`方法实现业务逻辑。
综上所述,Quartz通过精心设计的线程调度与执行流程,确保了任务的高效与稳定执行,展示了其强大的任务管理能力。
图搞懂Xxl-Job
今天继续深入探索,揭秘分布式任务调度平台Xxl-Job的架构原理。
核心概念讲解如下:
调度中心:为触发定时任务执行的独立Web服务,提供页面操作管理定时任务触发逻辑,依赖数据库共享数据,并支持集群模式。
执行器:具体执行任务逻辑的服务实例,每个执行器对应一个任务实例,并支持自定义名称,便于识别。
任务:定义的定时执行操作,执行器中可以包含多个任务。
架构实现原理详解:
搭建调度中心:下载源码,配置数据库连接信息,执行数据库初始化脚本,启动调度中心服务,访问控制台页面。
执行器和任务添加:创建执行器实例,指定任务名称,选择执行器,配置任务触发逻辑,如每秒执行一次。
任务触发机制:调度中心启动时开启调度线程,周期性查询数据库中的任务信息,根据预读时间筛选任务,划分任务执行时机,更新下次执行时间,实现精准触发。
任务触发优化:引入快慢线程池,异步处理任务触发请求,避免调度效率下降,提高任务执行效率。
选择执行器实例:通过路由策略(分片广播、一致性Hash、LFU、LRU、故障转移、忙碌转移等)选择执行器,确保任务均匀分布,提高执行效率。
执行器处理任务:执行器接收到请求后,创建JobThread线程处理任务,任务异步放入队列中,避免不同任务之间的干扰。针对单个执行器上的任务,设置阻塞处理策略,如单机串行、丢弃调度、覆盖之前调度等,以确保任务有序执行。
任务执行结果回调:任务执行完毕后,执行器异步将结果回传至调度中心,完成任务处理流程。
总结:Xxl-Job通过轻量级的设计,实现了一种任务触发与执行分离的架构模式,使得任务更加灵活,易于管理和扩展。从任务创建到执行,再到结果反馈,整个流程通过独立的服务组件和高效的策略实现,确保了任务调度的准确性和高效性。
xxl-job定时任务触发实现分析
在深入探讨《调度中心启动流程分析》中的调度任务启动源码时,重点解析了JobScheduleHelper类的start方法。此方法启动了两个关键线程:scheduleThread和ringThread。具体而言,scheduleThread线程和ringThread线程的run方法包含调度任务执行的逻辑。在分析这两个线程的运行机制前,提出以下两个问题以加深理解:
在xxl-job集群部署中,如何有效防止多个服务器同时调度任务?
在xxl-job集群部署时,避免多个服务器同时调度任务通过使用MySQL的悲观锁实现分布式锁。这确保了在任何时候,只有一个服务器能够访问和更新xxl_job_info表,有效防止了并发调度冲突。
如何实现定时任务触发机制?
定时任务的实现流程主要涉及定时任务的存储与调度。xxl-job通过xxl_job_info表记录定时任务信息,特别是下一次执行的时间戳。定时任务每执行一次,数据库中的该时间戳更新,以确定下一次触发时间。任务调度过程如下:周期性地从数据库中读取5秒内的任务,根据下一次触发时间决定是否执行,同时任务被放入时间轮中,由ringThread线程进行任务调度。
时间轮的概念及其在xxl-job中的应用。时间轮将一段时间分割为等分时间段,每个时间段关联对应任务。具体实现中,ringData结构以秒数(1-)为key,任务ID列表为value。ringThread线程的run方法通过获取当前秒数及前两个秒数的任务列表,触发任务执行,并清空已执行任务列表。此设计旨在避免长时间任务处理导致错过调度时机。
总结xxl-job的定时任务调度机制,核心在于时间轮的高效管理,结合数据库查询和线程调度策略,确保任务按计划有序执行。本文主要分析了定时任务的启动与调度流程,未来将会探讨任务执行的详细流程。通过解析上述内容,xxl-job提供了一种灵活、高效的任务调度解决方案,适用于大规模并发场景。
Spark-Submit 源码剖析
直奔主题吧:
常规Spark提交任务脚本如下:
其中几个关键的参数:
再看下cluster.conf配置参数,如下:
spark-submit提交一个job到spark集群中,大致的经历三个过程:
代码总Main入口如下:
Main支持两种模式CLI:SparkSubmit;SparkClass
首先是checkArgument做参数校验
而sparksubmit则是通过buildCommand来创建
buildCommand核心是AbstractCommandBuilder类
继续往下剥洋葱AbstractCommandBuilder如下:
定义Spark命令创建的方法一个抽象类,SparkSubmitCommandBuilder刚好是实现类如下
SparkSubmit种类可以分为以上6种。SparkSubmitCommandBuilder有两个构造方法有参数和无参数:
有参数中根据参数传入拆分三种方式,然后通过OptionParser解析Args,构造参数创建对象后核心方法是通过buildCommand,而buildCommand又是通过buildSparkSubmitCommand来生成具体提交。
buildSparkSubmitCommand会返回List的命令集合,分为两个部分去创建此List,
第一个如下加入Driver_memory参数
第二个是通过buildSparkSubmitArgs方法构建的具体参数是MASTER,DEPLOY_MODE,FILES,CLASS等等,这些就和我们上面截图中是对应上的。是通过OptionParser方式获取到。
那么到这里的话buildCommand就生成了一个完成sparksubmit参数的命令List
而生成命令之后执行的任务开启点在org.apache.spark.deploy.SparkSubmit.scala
继续往下剥洋葱SparkSubmit.scala代码入口如下:
SparkSubmit,kill,request都支持,后两个方法知识支持standalone和Mesos集群方式下。dosubmit作为函数入口,其中第一步是初始化LOG,然后初始化解析参数涉及到类
SparkSubmitArguments作为参数初始化类,继承SparkSubmitArgumentsParser类
其中env是测试用的,参数解析如下,parse方法继承了SparkSubmitArgumentsParser解析函数查找 args 中设置的--选项和值并解析为 name 和 value ,如 --master yarn-client 会被解析为值为 --master 的 name 和值为 yarn-client 的 value 。
这之后调用SparkSubmitArguments#handle(MASTER, "yarn-client")进行处理。
这个函数也很简单,根据参数 opt 及 value,设置各个成员的值。接上例,parse 中调用 handle("--master", "yarn-client")后,在 handle 函数中,master 成员将被赋值为 yarn-client。
回到SparkSubmit.scala通过SparkSubmitArguments生成了args,然后调用action来匹配动作是submit,kill,request_status,print_version。
直接看submit的action,doRunMain执行入口
其中prepareSubmitEnvironment初始化环境变量该方法返回一个四元 Tuple ,分别表示子进程参数、子进程 classpath 列表、系统属性 map 、子进程 main 方法。完成了提交环境的准备工作之后,接下来就将启动子进程。
runMain则是执行入口,入参则是执行参数SparkSubmitArguments
Main执行非常的简单:几个核心步骤
先是打印一串日志(可忽略),然后是创建了loader是把依赖包jar全部导入到项目中
然后是MainClass的生成,异常处理是ClassNotFoundException和NoClassDeffoundError
再者是生成Application,根据MainClass生成APP,最后调用start执行
具体执行是SparkApplication.scala,那么继续往下剥~
仔细阅读下SparkApplication还是挺深的,所以打算另外写篇继续深入研读~
2024-11-30 15:06
2024-11-30 14:58
2024-11-30 14:24
2024-11-30 13:53
2024-11-30 12:56