一些用户提交的耗时任务通常会异步执行,如果程序遇到意外情况停电、应用异常关闭等被终止,这就需要考虑到任务恢复了。
举个简单例子,用户上传了一个 csv 文件,需要解析并入库,解析到一半左右中断了。一般大家在处理这种情况的时候,在任务执行中都会存储哪些信息,如何存储,恢复?
如果涉及到集群,是不是考虑的要更多,比如任务的恢复必须由任务的发起方来进行,否则会找不到上传的那个文件,另外也要防止多个节点重复执行。
这一块想听听业内成熟的做法,尽量轻量化一点。
对了,后台是 Java 和 NodeJS。
1
MuaGeWang 2017-10-19 09:19:49 +08:00
叫用户再传一遍
|
3
wangxiaoer OP 重复传不太合适吧
|
4
zhouwei520 2017-10-19 10:07:29 +08:00
中断,超时或者失败,rollback,重新执行。
单系统,停电、应用异常关闭无解的好吧 智能多服务器多应用 |
5
zhouwei520 2017-10-19 10:07:45 +08:00
智能
|
6
zhouwei520 2017-10-19 10:07:51 +08:00
只能
|
7
mooncakejs 2017-10-19 10:10:28 +08:00
队列一般都有重试机制, 数据导入 能开事务开事务,不能开事务我也不知道。
|
8
wangxiaoer OP @zhouwei520 我的意思就是重新执行一般都需要记录哪些信息?执行中是不是要频发刷新任务进度,进度信息又存放在哪里?假如 90%多的时候异常退出,进度信息也没有持久化,难道从头在开始运行吗?
|
9
hcymk2 2017-10-19 10:22:40 +08:00
上传和解析不要放在一起。上传成功后就相应前台,之后通过 job 解析入库,成功后通过通知提醒用户。
|
10
gamexg 2017-10-19 11:21:04 +08:00 1
原来做渲染时任务记录直接存数据库。
原始文件和最终输出都是直接放到云储存。 任务中间虽然也有几个步骤,但是并没有保存中间状态,失败时重新执行整个任务。 任务执行每一子任务都有超时时间+心跳。 超时时间负责解决任子任务卡住的问题,当工作者执行耗时超过预定时间会杀死派生的任务进程强制失败。 调度器也会检查是否存在严重超时的任务。 心跳负责解决工作者挂掉的问题,有一个调度器定时检查心跳超时的任务,将这种标记为任务失败。 被标记为失败的任务会尝试重试 3 次,仍然失败就放弃。 本来是用任务队列做的,但是由于跨机房,任务队列很容易卡死,最终改为了长轮询。工作者长轮询查询是否存在新任务。数据库锁保证单个任务只分配给单个工作者。 这种需求任务数量少,单个任务耗时几小时,就不太在乎任务分配的性能了。 耗时最长的渲染工作是调用外部进程,没办法保存中间进度,也没保存中间状态用来恢复。 |
11
wangxiaoer OP @gamexg 失败重新执行感觉有点不合适,正常一次任务可能要很久的
|
12
gamexg 2017-10-19 11:51:41 +08:00
@wangxiaoer #11 额,任务恢复实现太麻烦了,除非经常失败没必要做吧?
真的想实现比较好的做法是拆分成子任务,单个子任务挂了重新开始,对其他子任务没影响。 |
13
wangxiaoer OP @gamexg 是的,所以先找一个相对稳妥的办法。
|
14
sujin190 2017-10-19 12:38:49 +08:00
正常情况下,异步任务都应该是做成可重入幂等的啊,这样失败了,任务应该还在啊,重新执行一遍就是了啊,否则,任务多了会很麻烦
|
15
wangxiaoer OP @sujin190 “可重入幂等” 具体怎么讲,能详细说说吗
|
16
sujin190 2017-10-19 14:16:09 +08:00
@wangxiaoer #15 很简单啊,就是相同任务,无论什么情况,无论执行多少遍,结果都一样
|