皮皮网

皮皮网

【抓取赛事源码】【bsv源码】【actors源码】job源码

时间:2024-11-19 03:43:55 分类:热点

1.Spark-Submit 源码剖析
2.JobScheduler的使用和原理
3.xxjob使用
4.xxjob有哪几种开发模式?
5.JobIntentService源码解析
6.技术人生阅读源码——Quartz源码分析之任务的调度和执行

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方式获取到。

       那么到这里的bsv源码话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,设置各个成员的值。接上例,actors源码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则是qvector源码执行入口,入参则是执行参数SparkSubmitArguments

       Main执行非常的简单:几个核心步骤

       先是打印一串日志(可忽略),然后是创建了loader是把依赖包jar全部导入到项目中

       然后是MainClass的生成,异常处理是ClassNotFoundException和NoClassDeffoundError

       再者是生成Application,根据MainClass生成APP,最后调用start执行

       具体执行是SparkApplication.scala,那么继续往下剥~

       仔细阅读下SparkApplication还是挺深的,所以打算另外写篇继续深入研读~

JobScheduler的使用和原理

        JobScheduler主要用于在未来某个时间下满足一定条件时触发执行某项任务的情况,涉及的条件可以是网络、电量、时间等,例如执行特定的网络、是否只在充电时执行任务等。

        JobScheduler类负责将应用需要执行的任务发送给框架,以备对该应用Job的调度,是一个系统服务,可以通过如下方式获取:

        JobInfo是传递给JobScheduler类的数据容器,它封装了针对调用应用程序调度任务所需的各种约束,也可以认为一个JobInfo对象对应一个任务,JobInfo对象通过JobInfo.Builder创建。它将作为参数传递给JobScheduler:

        JobInfo.Builder是JobInfo的一个内部类,用来创建JobInfo的Builder类。

        JobService是JobScheduler最终回调的端点,JobScheduler将会回调该类中的onStartJob()开始执行异步任务。它是一个继承于JobService的抽象类,做为系统回调执行任务内容的终端,JobScheduler框架将通过bindService()方式来启动该服务。因此,用户必须在应用程序中创建一个JobService的子类,并实现其onStartJob()等回调方法,以及在AndroidManifest.xml中对它授予如下权限:

        注意在AndroidManifest.xml中添加权限

        当任务开始时会执行onStartJob(JobParameters params)方法,如果返回值是false,则系统认为这个方法返回时,任务已经执行完毕。如果返回值是true,那么系统认为这个任务正要被执行,执行任务的重担就落在了你的肩上。当任务执行完毕时你需要调用jobFinished(JobParameters params, boolean needsRescheduled)来通知系统。

        当系统接收到一个取消请求时,系统会调用onStopJob(JobParameters params)方法取消正在等待执行的任务。很重要的一点是如果onStartJob(JobParameters params)返回false,那么系统假定在接收到一个取消请求时已经没有正在运行的任务。换句话说,onStopJob(JobParameters params)在这种情况下不会被调用。

        需要注意的是这个Job Service运行在主线程,这意味着你需要使用子线程,handler,或者一个异步任务来运行耗时的操作以防止阻塞主线程。

        Google官方的Sample: /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机制

xxjob使用

       å‚考文献 /p/fabeab

        源码版本 /xuxueli/xxl-job/releases

        1). springboot为例:复制源码xxl-job-executor-sample-springboot项目中com.xxl.job.executor.core.config.XxlJobConfig到自己项目

        2). 复制对应的配置文件到自己项目,xxljob依赖

        3). 编写定时任务demo

        补充:

        1. 报警邮件配置(发送者),需要在对应邮箱设置中开启SMTP获取授权码:

xxjob有哪几种开发模式?

       XXL-Job支持两种模式的任务开发,BEAN和GLUE。

       GLUE是在WebIDE上进行开发,源码维护在调度中心,支持Java、Shell、Python、NodeJS、PHP、rivz源码PowerShell。

       BEAN模式开发更多的还是在业务系统中

       BEAN模式有两种方式:类形式、方法形式。

       其中类型是就是继承IJobHandler,实现其中任务方法,并注入到执行器容器内即可。

       一个任务一个类,无需框架,直接用main函数调用即可。

JobIntentService源码解析

       Android 8.0引入了更严格的系统资源管控,包括后台限制规则。

       在Android 8.0中,禁止应用在后台运行时创建Service。

       若应用在后台运行,将会收到错误提示。

       JobIntentService是Android 8.0中新增的类,继承自Service。

       该类用于执行加入队列的任务。对于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`方法实现调度流程,包含三个主要阶段:获取到达触发时间的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通过精心设计的线程调度与执行流程,确保了任务的高效与稳定执行,展示了其强大的任务管理能力。