后台事务介绍
EAS后台事务服务介绍
目 录
7.3. 后台事务服务堵塞,某个后台事务一直处于执行中,堵塞了其他后台事务。
1. 简介
什么是后台事务服务?
• 是后台运行的系统服务,类似windows执行计划;
• 一种后台运行的作业调度;
• 依赖于Quartz调度框架;
• 通过线程池来管理。
例如:有这样一个任务:每个月的最后一天,计算所有员工工资。则可以后台事务来实现和管理。
首先定义一个后台事务,然后选择相应的任务,这里的任务就是“计算所有员工资”,再选择调度计划或调度周期,这里调度计划就是“每个月的最后一天”,最后发布后台事务就可以了,到每月的最后一天自动会计算所有员工的工资。
2. 功能说明
2.1. 后台事务定义
可以通过后台事务定义,定义一个后台事务服务。
点击新增按钮。
输入后台事务名称
选择任务
从“选择任务”对话框中选择需要的任务点击确定退出
如果所选任务有参数请输入有意义的参数
设置调度计划也就是执行计划
选择调度计划类型
详细设置选定类型的调度计划
设置完成后点击完成,退出调度计划设置界面
设置互斥控制(后台事务互斥标识,一般保持默认即可,参考4.6互斥任务)
设置指定服务器(默认自动分配,也可指定到某一个实例上执行)
设置好后就可以点击“保存”按钮保存后台事务
保存成功
保存后的后台事务如果需要运行需要点击“发布”按钮进行发布
点击“发布”按钮后弹出“发布事务”对话框
点击“发布事务”对话框下面的“发布”按钮进行发布
这样一条后台事务就定义完成并已经生效
2.2. 后台事务定义列表
列出所有已经定义的后台事务,并可以启动/禁用后台事务
2.3. 后台事务监控
可以查看后台事务的运行情况,类似工作流监控。主要包括后台事务的名称、状态、发起人、创建时间等信息。
3. 主要类文件说明
3.1. 服务端(scheduler)
3.1.1. 后台事务服务启动
eas\server\profiles\server*\config\listenerconfig.data
<listener name="com.kingdee.bos.service.scheduler.BOSSchedulerService" enable="true" failOnError="false" />
主要功能:启动后台事务引擎
eas/server/profiles/server*/config/bosconfig.xml
<configitem name="scheduler">
<attribute key="enable" value="true" />
</configitem>
主要功能:启动后台事务服务,没有参数默认为true
注意:
在管理控制台反部署数据中心后,应该重启服务器;否则将导致服务器每隔一定时间输出数据中心无法访问的日志(除此之外,也就是浪费一点服务器内存,没有其他副作用)。
3.1.2. 后台事务服务类
com.kingdee.bos.service.job.core. JobService
3.1.3. 流程定义转后台事务定义
com.kingdee.bos.workflow.store.util. JobServiceUtil
3.1.4. 后台事务服务状态维护
com.kingdee.bos.service.job.core. ClusterStateManager
主要功能:
在数据 T_Job_Service 表中维护当前在线的后台事务服务器列表;
检查停止执行的后台事务服务器并回收其加载但未执行完的后台事务实例
3.1.5. 后台事务实例加载器
com.kingdee.bos.service.job.core. JobLoader
定期搜索T_Job_Inst表加载待执行的后台事务实例
3.1.6. 后台事务触发器加载器
com.kingdee.bos.service.job.core. TriggerLoader
定期搜索T_Job_Trigger表加载新发布的后台事务触发器
3.1.7. 后台事务队列
com.kingdee.bos.service.job.core. WaitingJobs/ReadyJobs/RunningJobs
等待、就绪队列及当前执行任务(对已就绪的大事务及互斥事务进行了管理)
3.1.8. 后台事务定义触发
com.kingdee.bos.service.job.pulse. TimerPulseSource
定期检查后台事务触发器的触发时间,在下一个触发时刻“快”到达时,根据后台事务定义生成后台事务实例。
3.2. 客户端(bs_job)
3.2.1. 后台事务定义配置
com.kingdee.eas.base.job.client.JobProcessManager
3.2.2. 后台事务定义列表(已发布的)
com.kingdee.eas.base.job.client.JobProcessDefineListUI
注:以”~”开头的后台事务定义不允许禁用或启用。
3.2.3. 后台事务实例列表
com.kingdee.eas.base.job.client.JobProcessInstanceListUI
注:以”~”开头的后台事务实例不允许撤消或挂起。
4. 后台事务特性
4.1. 非持久化后台事务
后台事务分为持久化事务和非持久化事务,持久化事务指写入数据库持久化的事务,可以被其他实例加载执行,可以在后台事务监控查到执行记录;非持久化事务是系统内部缓存的事务,只能在本实例执行。
在登陆EAS系统后,进入后台事务管理,在后台事务定义的界面上我们是不能选择是定义持久化事务和非持久化事务的,通过在EAS系统中定义的后台事务默认都是持久化事务的。如果我们要定义非持久化后台事务,就必须通过代码来实现。
4.2. 错过策略
在后台事务定义的时候,可以进行设置后台事务的错过策略,有两种情况,一种是“立即执行”,另一种是“忽略不计”,其中这两种是怎样工作的呢?
在后台事务定义的时候,后台事务错过策略信息是保存在T_JOB_DEF的fmissedtimeout字段中,设置后台事务的错过策略为立即执行,这个字段保存的值为-1,设置为忽略不计,这个字段保存的值为0。
当生成后台事务任务时,如果过期时间为空,则首先判断JobDef的missedTimeout是否为0,如果为零,表示忽略不计,对忽略不计这种情况,系统会默认设置它的过期时间,在任务执行的时候,如果超过这个过期时间,就设置这个后台事务实例的状态为“已错过”;对于立即执行这种情况,就不会去设置它的过期时间,expiredTime这个值为null,表示永不过期。
4.3. 人工干预(撤销,挂起,唤醒)
对已接收,重新调度,已就绪,等待中的后台事务实例可进行撤销和挂起操作,对已挂起的后台事务实例可以进行唤醒操作,已错过的后台事务可以进行修复操作(其实质也就是重新调度),对运行中的后台事务不能够做任何操作。
4.4. 调度计划时间
依赖于Quartz调度框架,Quartz是opensymphony组织专攻job scheduling领域又一个开源利器,可以到http://www.opensymphony.com/quartz查看详细信息。
Quartz是轻量级的组件,开发人员只需要加载单独的jar包就可以利用Quartz强大的日程安排功能。当然,假如你为Quartz配备了数据库持久化任务的特性,Quartz也可以很好的利用这一点,从而在机器重启后还能够记住你原先安排的计划。
目前的Quartz实现中,存在两种Trigger,SimpleTrigger和CronTrigger。SimpleTrigger:用来完成一些比如固定时间执行的任务,比如:从现在开始1分钟后等等;CronTrigger: 用来执行calendar-like的任务,比如:每周五下午3:00,每月最后一天等等。
后台事务触发器的调度计划时间表达式是保存在数据库表T_JOB_TRIGGER的fschedulePlan字段中,String schedulePlan=schedule.getType().toString()+":"+schedule.getDefine();由这条语句可知,其值由两部分组成。分别为调度类别和调度的定义,其中调度定义是Quartz的cron 表达式的格式,后台事务获取下一次触发时间就是根据这个表达式来得到的,首先根据这个表达式可以新建一个CronTrigger对象,通过这个对象及上一次的触发时间就可以得到下一次触发时间了:quartzTrigger.getFireTimeAfter(lastTriggeredTime)。
下面是对Quartz的cron 表达式的格式的说明:
Quartz 用 cron 表达式存放执行计划。引用了 cron 表达式的 CronTrigger 在计划的时间里会与 job 关联上。Quartz 提供七个域。下表列出了 Quartz cron 表达式支持的七个域。
名称 | 是否必须 | 允许值 | 特殊字符 |
秒 | 是 | 0-59 | , - * / |
分 | 是 | 0-59 | , - * / |
时 | 是 | 0-23 | , - * / |
日 | 是 | 1-31 | , - * ? / L W C |
月 | 是 | 1-12 或 JAN-DEC | , - * / |
周 | 是 | 1-7 或 SUN-SAT | , - * ? / L C # |
年 | 否 | 空 或 1970-2099 | , - * / |
月份和星期的名称是不区分大小写的。FRI 和 fri 是一样的。域之间有空格分隔,这和 UNIX cron 一样。无可争辩的,我们能写的最简单的表达式看起来就是这个了:* * * ? * *,这个表达会每秒钟(每分种的、每小时的、每天的)激发一个部署的 job。
Quartz cron 表达式支持用特殊字符来创建更为复杂的执行计划:
*星号:使用星号(*) 指示着你想在这个域上包含所有合法的值。例如,在月份域上使用星号意味着每个月都会触发这个 trigger。
表达式样例:0 * 17 * * ?
意义:每天从下午5点到下午5:59中的每分钟激发一次 trigger。它停在下午 5:59 是因为值 17 在小时域上,在下午 6 点时,小时变为 18 了,也就不再理会这个 trigger,直到下一天的下午5点,在你希望 trigger 在该域的所有有效值上被激发时使用 * 字符。
? 问号:? 号只能用在日和周域上,但是不能在这两个域上同时使用。你可以认为 ? 字符是 "我并不关心在该域上是什么值。" 这不同于星号,星号是指示着该域上的每一个值。? 是说不为该域指定值。
不能同时这两个域上指定值的理由是难以解释甚至是难以理解的。基本上,假定同时指定值的话,意义就会变得含混不清了:考虑一下,如果一个表达式在日域上有值11,同时在周域上指定了 WED。那么是要 trigger 仅在每个月的11号,且正好又是星期三那天被激发?还是在每个星期三的11号被激发呢?要去除这种不明确性的办法就是不能同时在这两个域上指定值。只要记住,假如你为这两域的其中一个指定了值,那就必须在另一个字值上放一个 ?。
表达式样例:0 10,44 14 ? 3 WEB
意义:在三月中的每个星期三的下午 2:10 和 下午 2:44 被触发。
, 逗号:逗号 (,) 是用来在给某个域上指定一个值列表的。例如,使用值 0,15,30,45 在秒域上意味着每15秒触发一个 trigger。
表达式样例: 0 0,15,30,45 * * * ?
意义:每刻钟触发一次 trigger。
/ 斜杠:斜杠 (/) 是用于时间表的递增的。我们刚刚用了逗号来表示每15分钟的递增,但是我们也能写成这样 0/15。
表达式样例: 0/15 0/30 * * * ?
意义:在整点和半点时每15秒触发 trigger。
- 中划线:中划线 (-) 用于指定一个范围。例如,在小时域上的 3-8 意味着 "3,4,5,6,7 和 8 点。" 域的值不允许回卷,所以像 50-10 这样的值是不允许的。
表达式样例: 0 45 3-8 ? * *
意义:在上午的3点至上午的8点的45分时触发 trigger。
L 字母: L 说明了某域上允许的最后一个值。它仅被日和周域支持。当用在日域上,表示的是在月域上指定的月份的最后一天。例如,当月域上指定了 JAN 时,在日域上的 L 会促使 trigger 在1月31号被触发。假如月域上是 SEP,那么 L 会预示着在9月30号触发。换句话说,就是不管指定了哪个月,都是在相应月份的时最后一天触发 trigger。
表达式样例: 0 0 8 L * ?
意义:在每个月最后一天的上午 8:00 触发 trigger。在月域上的 * 说明是 "每个月"。当 L 字母用于周域上,指示着周的最后一天,就是星期六 (或者数字7)。所以如果你需要在每个月的最后一个星期六下午的 11:59 触发 trigger,你可以用这样的表达式 0 59 23 ? * L。当使用于周域上,你可以用一个数字与 L 连起来表示月份的最后一个星期 X。例如,表达式 0 0 12 ? * 2L 说的是在每个月的最后一个星期一触发 trigger。
注意:不要让范围和列表值与 L 连用,虽然你能用星期数(1-7)与 L 连用,但是不允许你用一个范围值和列表值与 L 连用。这会产生不可预知的结果。
W 字母:W 字符代表着平日 (Mon-Fri),并且仅能用于日域中。它用来指定离指定日的最近的一个平日。大部分的商业处理都是基于工作周的,所以 W 字符可能是非常重要的。例如,日域中的 15W 意味着 "离该月15号的最近一个平日。" 假如15号是星期六,那么 trigger 会在14号(星期四)触发,因为距15号最近的是星期一,这个例子中也会是17号(译者Unmi注:不会在17号触发的,如果是15W,可能会是在14号(15号是星期六)或者15号(15号是星期天)触发,也就是只能出现在邻近的一天,如果15号当天为平日直接就会当日执行)。W 只能用在指定的日域为单天,不能是范围或列表值。
# 井号:# 字符仅能用于周域中。它用于指定月份中的第几周的哪一天。例如,如果你指定周域的值为 6#3,它意思是某月的第三个周五 (6=星期五,#3意味着月份中的第三周)。另一个例子 2#1 意思是某月的第一个星期一 (2=星期一,#1意味着月份中的第一周)。注意,假如你指定 #5,然而月份中没有第 5 周,那么该月不会触发。
4.5. 事务动态优先级
动态优先级由两部分生成,一是计划执行时间,另一部分是静态优先级(后台事务定义界面设置的优先级);计划执行时间优先于静态优先级;即事务实例默认按照计划执行时间排队执行,当两个事务实例的计划执行时间相同,而他们静态优先级不同时,则按照静态优先级决定执行顺序。
4.6. 互斥任务
互斥任务:同一个实例,对于必须互斥执行的多个任务,通过赋予相同的互斥任务组号,使得后台事务服务调度这些任务时,保证同组号任务是互斥执行的,简单地来书就是保证一组互斥任务串行地执行,运行时队列只允许存在互斥任务组中的一个后台任务实例。
在新建后台事务定义的时候可以为该后台事务定义指定互斥任务组号,默认其格式为:G::业务功能名称(不带包名)。
在工作线程ThreadWork的run()方法是从就绪队列中取出后台事务实例进行执行,从就绪队列(ReadyJobs)取出后台事务实例后,首先获得后台事务实例(Job)的互斥任务组号,如果是互斥任务,且已有同组任务在执行,则延迟执行,如果是互斥任务但没有同组任务在执行,则登记互斥任务组号这样就可以保证在运行队列中,互斥任务组在某个时候只有一个属于该互斥任务组的后台事务实例在执行。
4.7. 日志消息
后台事务实例(Job)执行过程中的日志信息(JobLog)保存在数据库表T_JOB_LOG中,该表中的日志消息记录(JobLog)是通过fownerid字段来和后台事务实例(Job)关联的,它保存的就是后台事务实例(Job)的ID。
日志消息类的type属性是Type(JobLog中自定义的类型)类型,用来说明该日志消息的类型,有“Info”,“Warn”和“Error”三种类型,日志消息类用的地方很多,常见的是当后台事务实例运行出错时,我们需要记录出错信息,这是设置type属性为Error类型,供后台事务管理人员查看,也可以用来记录后台事务执行成功,此时应该设置为Info类型。
下图是后台事务实例(Job)执行失败时的日志消息显示
4.8. 大小任务
在新建后台事务定义(JobDef)的时候,会设置这个后台事务定义是属于大任务还是小任务,其分类是按照后台事务实例执行时间来划分的,在后台事务定义对象中是由issmalljob属性来标识该特性的。
我们不论是通过EAS系统的后台事务管理界面定义的后台事务定义,还是直接在代码中调用JobDef的构造函数(可以通过构造函数实现小任务定义),默认都是“大任务”。
在后台事务执行成功后,会进行一些后续处理,其中adjustJobDef(Job job)就是用来调整该后台事务是属于大事务还是小事务。是根据执行时间来进行调整的。在bosconfig.xml配置文件中设置了时间边界值,“小任务执行时间上限”如果小任务执行时间大于该值,则以后产生的同类后台事务实例采用大任务调度。
如果是大任务,且已达最大线程数,则延迟,如果没有达到最大线程,则把大任务的计数器增加1,这里的小任务和大任务的最大线程数是在bosconfig.xml中配置的“最小并发度”,这样可以保证大任务不会占用所有的工作线程。
4.9. 配置文件参数说明
后台事务配置文件eas/server/profiles/server*/config/bosconfig.xml,每个实例下一份,文件中scheduler后台事务配置项,常用配置参数如下:
enable——后台事务服务是否启动,合法值:true或false,没有参数默认为true
local_ip——人工指定实例标识IP,当自动获取的IP地址无法用于服务器间连接时,人工指定可用的IP,没有参数默认从网卡自动获取一个IP(如果是多网卡或者使用了虚拟IP,则必须使用此参数指定一个IP地址,因为后台事务运行依赖于此IP进行任务分发加载,如果多IP当自动获取的IP变了,会导致后台事务不执行)
clusterName——集群标识,表示当前实例所在的后台事务集群,没有参数默认standalone
maximal_concurrency——最大并发数,合法值:3~100,没有参数默认6
minimal_concurrency——最小并发数,合法值:1~99,没有参数默认最大并发数减2
job_execution_timeout——任务执行超时,单位:秒,合法值:10~900,没有参数默认60
cluster_beat_signal_interval——集群信号交换间隔,每隔指定时间刷新当前服务实例的状态信息(T_Job_Service),单位:分钟,合法值:1~10,没有参数默认5
cluster_beat_signal_timeout——集群信号超时,超过指定时间未刷新状态的服务实例被判定为失效,单位:分钟,合法值:15~60,没有参数默认15,且不会小于集群信号交换间隔3倍时间
job_loader_delay——服务器启动时,后台事务加载任务的延时,单位:秒,合法值≥30,没有参数默认30
default_trigger_isolation_level——触发器trigger隔离级别,默认server
none — 无隔离,当前服务实例提交的触发器允许其他服务实例处理;
server —当前服务实例提交的触发器只允许同一个IP地址的其他服务实例处理;
cluster - 集群隔离,可以处理同一个后台事务集群的服务实例提交的触发器。
default_job_isolation_level——任务实例的隔离级别,默认server
none — 无隔离,当前服务实例提交的后台事务实例允许其他服务实例处理;
server — 服务器隔离(IP隔离),当前服务实例提交的后台事务实例仅允许同一个IP地址上的服务实例处理;
instance — 实例隔离,当前服务实例提交的后台事务实例不允许其他服务实例处理;
cluster - 集群隔离,当前服务实例提交的后台事务实例仅允许同一个后台事务集群的服务实例处理。
load_job_isolation_level——加载任务实例的隔离级别,取值为1~4个隔离级别组合,“|”隔开
none — 无隔离,可以处理所有无隔离实例提交的后台事务实例;
server — IP隔离(服务器隔离),可以处理同一个IP地址上IP隔离的服务实例提交的后台事务实例;
instance — 服务实例隔离,可以处理提交到本服务实例的后台事务实例;
cluster - 集群隔离,可以处理同一个后台事务集群的服务实例提交的后台事务实例。
(load_job_isolation_level参数目前只有8.5版本支持,需要更新补丁PT158318,低版本后续会回迁,高版本需升级sp2)
5. 后台事务主要数据库表
T_JOB_DEF 后台事务定义表,后台事务定义发布后,生成后台事务定义数据
FjobDefId | 定义ID,唯一标识 |
Ftitle | 事务定义标题 |
FhandlerWrapper | 调度业务方法以及参数信息等 |
Fmutex | 事务互斥控制标识(同一个实例相同标识的任务串行执行) |
T_JOB_TRIGGER 后台事务触发器表,后台事务定义发布后,生成触发器数据,FjobDefId与事务定义表关联
FschedulePlan | 调度计划 |
FselectedServer | 指定执行实例 |
FisValid | 是否失效 |
FholderId | 加载此触发器的实例标识 |
FisolationBoundary | 加载隔离边界(标识此触发器可被符合该隔离条件的实例加载,详见隔离边界) |
FtriggeredCount | 已触发次数 |
FlastJobInst | 最后触发任务实例ID |
FlastTriggeredTime | 最后触发时间 |
FuseCalendar | 是否使用工作日历 |
FinWorkingDay | 使用工作日历时,指定工作日或非工作日执行(8.0版本更新补丁PT143669,8.5版本更新补丁PT155669,8.2版本暂不支持,8.6以上版本均支持) |
T_JOB_INST 后台事务任务实例表,实例加载触发器数据,定时检查触发器,快到下一次触发时间的时候,生成任务实例数据,FjobDefId与事务定义表关联
Ftitle | 任务实例标题(一般由【事务定义标题_计划时间戳】组成,包含【{事务定义标题}测试,】的任务为人工点击测试产生的任务) | |
FuserId | 任务执行时上下文用户id(默认为管理员,可以在后台事务定义【执行人】配置) | |
FscheduledTime | 计划时间(触发器根据调度计划生成,计划开始执行的时间) | |
FstartedTime | 开始时间(任务实例被加载后,正式开始执行的时间) | |
FinishTime | 结束时间(任务实例执行结束的时间) | |
FpriorState | 任务前一状态 | Created【已接收】、ReScheduled【重新调度】、 Waiting【等待中】、Ready【已就绪】、 Running【执行中】、Suspended【已挂起】、 Failed【已失败】、Complete【已完成】、 Aborted【已撤销】、Missed【已错过】 |
Fstate | 任务当前状态 | |
FstateChangedTime | 最后任务状态变更时间 | |
FholderId | 加载此触发器的实例标识 | |
FisolationBoundary | 加载隔离边界(标识此触发器可被符合该隔离条件的实例加载,详见隔离边界) | |
FjobType | SmallJobs【小任务】、BigJobs【大任务】、 WfJobs【工作流任务】、MajorJobs【重要任务】 | |
任务类型(8.5更新补丁PT158318,8.6更新补丁PTM158682,其他版本暂不支持) |
T_JOB_SERVICE 后台事务运行实例表,每个启用后台事务服务的实例,都会在这个表写入一条数据,以【实例名@IP+端口】作为唯一标识,例如server1@127.0.0.1:11034
FInstanceId | 实例标识,取管理控制台配置的实例名+网卡上读取的第一个IP和端口 |
FServerId | 网卡上读取的第一个IP |
FLocalIPs | 网卡上读取的所有IP,包含多网卡和虚拟IP的情况 |
FHostName | 网卡所在服务器机器名 |
FEASInsName | 管理控制台配置的实例名 |
FLastUpdateTime | 最后刷新时间(数据库时间,每5分钟刷新一次,如出现异常刷新,可能多个实例在刷新同一条数据,即IP+端口标识重复了) |
FClusterName | 实例所在后台事务集群标识,默认为standalone |
6. 隔离边界
none | 无隔离,即所有连接到这个数据中心的实例都可以加载此任务(触发器) |
instance | 实例隔离,即只有指定(IP+端口)的实例才能加载此任务(触发器没有实例隔离) |
server | 服务隔离,即只有指定(IP)的实例才能加载此任务(触发器) |
cluster | 后台事务介绍EAS后台事务服务介绍 目 录1. 简介 2. 功能说明 2.1. 后台事务定义 2.2. 后台事务定义列表 2.3. 后台事务监控 3. 主要... 点击下载文档 上一篇:后台事务问题分析汇总下一篇:单据已在流程队列中请稍后操作 本文2024-09-22 20:17:15发表“eas cloud知识”栏目。 您需要登录后才可以发表评论, 登录登录 或者 注册 最新文档
热门文章 阅读排行确认删除? 取消确定 |