首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

分布式任务系统cronsun

一、任务系统

图 1

图 2

说任务系统的话大家想起的就是要执行任务了,什么时间什么地点做什么事情。图 1 是简单的任务,在每天 8 点输出Hello Gophers!,大家用的比较多的任务系统就是 crond,其实这个系统(图 2)也很简单,就是守护进程加一个任务列表。

早期的 cron

说一下早期的 cron,早期的时候(大概在80 年代)在 Unix 系统里面 cron 运行逻辑

1.读/usr/lib/crontab 文件

2.如果有命令要在当前时间执行,就用 root 用去执行命令

3.每秒钟去运行一次,有就执行,没有就重复,比较简单

支持多用户的 cron

-Unix System V,1983

1. 启动的时候读取所有用户下的.crontab 文件

2. 计算出每个 crontab 文件里需要执行的命令的下一次执行时间

3. 把这些命令按下一次执行时间排序后放入队列里

4. 进入主循环

计算队列里第一个任务的执行时间与当前的时间差

Sleep 直到第一个任务执行时间

后台执行任务

计算这个任务的下一次执行时间,放回队列,排序

后面发展成支持多用户的,这时候的执行算法改了。这相当于按照时间顺序排列,谁先执行的就放在那里,计算现在的时间与下个时间间隔,再让程序暂停,需要时唤醒程序执行,然后重复。

近代的 cron

Linux,1991

1. Vixiecron(PaulVixie1987)

2. Version3Vixiecron(1993)

3. Version4.1ISCCron(2004)

4. anacron,dcron,fcron

现在的话 90 年代,大多数的都是用 4.0 的版本。大家用了这么久,基本都是在一些单机上跑一些任务,也是这样的操作。功能很简单,一个时间的规则,一个命令,如果公司有很多服务器的话,维护起来就不方便了,必须得一台一台去管理的或者是用脚本管理,多机器的情况下任务维护成本较高。

而且如果单机的话,如果失败了之后怎么办?就无法继续了,如果能做成分布式的就好了。

二、分布式任务系统

分布式任务系统特点

分布性

对等性

并发性

缺乏全局时钟

故障总是会发生

分布式系统有什么特点呢?大概的特点就不延伸了,大家可以理解为把一个简单的软件放在多台机器上,然后多台机器是都可以完成这个任务的。那么分布式的 crond 的问题,怎么解决呢?

图 3

第一个就是把守护进程做成多个分布式的进程(图 3),把命令分布在数据库里面,这是最简单的实践方式。

市面上的一些任务系统

Azkaban

Chronos

Airflow

dkron

swoole-crontab

Saturn

现在我们也想用一个这样的东西,一开始的时候找了市面上的方案,如上述现在市面上有很多方案,国内国外都有,最后一个是唯品会弄的,我挑几个讲一下。

1.Azkaban 是一个 Hadoop 上的任务管理,提供功能清晰,简单易用的 Web UI界面,也提供 job 配置文件快速建立任务和任务之间的依赖关系等等好处,但只能对Hadoop做任务管理,不符合我们的要求,我们的要求是替换单机版的crond。

2.Chronos 适合在容器编排管理工具上的调动,里面全部是替代了crond,里面有 UI,也有灵活的调度,但是要依赖于容器,对于我们来说应该还有更好的方案。

3.Dkron 这个就比较接近我们想要的东西,比较简单,高可用,也可控。但是不好的就是对任务的支持比较简单,而且都跑在容器上,相当于替换成容器。因为我们的机器很多都是本地任务,需要无缝替换 crond,因此也不考虑。

需求

对很多任务系统进行考察之后,我们有一下需求:

可替换crond

分布式、高可用

支持多种任务属性

易用

易部署

因此,我们开发了 cronsun。

三、cronsun

图 4

图 4 是cronsun 的系统架构,简单来说就是把任务存储在一个分布式etcd里,单个 crond 部署成一个服务,也就是node.1\2\3等等部署下去,再由 web 界面去管理。

cronsun 特性

部署简单

Web界面统一管理任务

任务失败重试

任务失败邮件提醒

多机单任务(防止单机挂掉任务不按时执行)

单机任务并行数限制

执行单次任务

多机器严格的时间间隔任务

支持安全性配置,可以限制任务脚本的后缀和执行用户

....

现在看一下cronsun 的特性。首先第一点就是部署简单,只需要在每个机器上部署crond 节点,再部署一个界面管理就可以了。如果 cronweb 挂掉了,只是这个界面不能对任务进行更新,但是不影响任务节点的运行,也就不影响任务的执行。其他的任务属性也讲了,最主要的是对任务有几种任务类型,就是可以在单台机器替换crond ,也解决单点的问题。比如说某个机器死了另外一台机器就会执行这个任务,保证任务执行。

cronsun 主要组件

图 5

cronsun主要有 3 个主件,都是通过etcd通讯的。cronnode 负责节点的分组及节点的状态,croeweb 是管理任务的、执行结果都可以在上面看。

任务类型

普通任务,和 crontab 中的任务一样

单机单进程任务,普通的 crontab 任务是单机的,如果执行任务的机器出现问题,任务可能执行失败。 cronsun 提供此任务类型是保证有多台机器可以执行一个任务,但在执行任务被执行时,只有一台机器在执行任务

一个任务执行间隔内允许执行一次,这个类型的任务和单机单进程任务类似,但限制更严格。因为多台机器间,时间可能会不一致,而某些任务要求执行的时间间隔要严格一致时,可以考虑采取这种类型

刚才说的任务就是这 3 种类型,单机单进程是只想在一台机器上执行,有 n 个节点,但是只会在一台机器上执行结果。此外还有一种情况,假如有3台机器,每台机器的时间不一致的话,这种任务保证在一个时间间隔内,不管机器时间差怎样,保证只执行一次,不重复执行,解决机器时间不同步的情况。

任务属性

失败重试

超时设置

安全设置

同时执行任务数设置

分组设置

任务的属性也大概说一下,如果随便填任务的话,web 任务界面暴露出去人家随便填几个任务就可以攻击你,安全设置只要加了脚本的后缀(就是本机器有的脚本),假如你的机器是安全的,那么整个系统就是安全的。还有同时执行任务数量设置,还有分组设置便于方便管理的。

任务定时器

图 6

定时器,跟crontab 是一样的,只是多了一个秒级。crontab 便于集中管理,多台服务器的时候就比较方便,保证了不会单点失败。还有就是简单的任务调度,web 是通过 API 来调度的,如果想使用的话稍微看一下 API 就可以调用了,整个系统大概就是这样。

四、心得体会

说一个开发过程中的体会。

第一个是方案的选择,方案选择一开始的时候基本都有这样的问题,你到底要做什么东西,系统要搞很多东西,我想调度,我想备份,能达成多种任务的系统里面。另外一种就是我把我想要的东西某个点做的很好,基于我们的人力物力,而且我们做的足够好,至于后面想扩展的时候能够扩展就可以了。

timer 的使用

图 7

如图 7 是一个典型的运用场景,我先跑一个任务,假如这个任务超时了就设置超时。在监听的过程中,有任务就执行,没任务就执行超时处理。

图 8

刚才的使用只是单次的话是没有问题的,但是在 for 循环里面会每次循环的话都会新建一个timer,这样的情况在要求性能比较高的场合,这是不可行的。有什么替代的方法呢?

图 9

图 10

熟悉的小伙伴应该就会想到直接做一个tick(图 9 ),自动给出消息,但是这个代码有一些问题,例如上面的代码,这个代码假如 1 秒之后没有了就超时。有个执行(图 10),如果你在这里可以直接刷新的话,这个超时的时候不会刷新的。

图 11

如果想超时也能刷新的话就需要做一些改造(图 11)。改造后就会刷新它,来的时候就会刷新超时,处理完了第一个,再处理完第二个,这样就可以解决 timer up 的问题。

goroutine 退出

图 12

第二个是 goroutine 的退出,大家可能有这种习惯就是每当起任务的时候都会起goroutine ,这是不好的习惯。解决的办法是就是限定一定的 goroutine,限定 goroutine 的数量而防止流量暴涨的后续问题(图 12),这是比较好的方案。

大家可以看一下 goroutine 退出的机制,每起一个goroutine ,就起一个监听,退出的时候就等待 goroutine 退出,再结束。

图 13

这里有个问题,这种方式只适合 goroutine 一跑就结束的形式,并不能通过信号去让goroutine 的退出。如果要通过信号控制 goroutine 的退出怎么办呢?需要有一个等待的函数(图 13),就是退出接受信号的函数。

图 14

具体是怎么实现的呢?如图 14函数监听退出的信号,goroutine 接到信号就直接退出,在外面的时候就等待,整个退出机制就很完善了。

图 15

图 16

但是以上情况是如果有一个信号退出的时候所有 goroutine 就会退出了,如果想实现链式的退出怎么办呢?就需要使用到信号传递了(图15)。可以这么做(图16),如图信号传递在第一个结束后再做传递,第二个监听完退出再传递,如此类推到所有退出完毕,就可以实现链式的有秩序退出。

语言的选择

最后再来说一下为什么选择 Go 语言来做开发语言,总的来说可以总结为以下几点:

简单、开发效率高

部署简单,只需一个二进制文件,无依赖

适合自己的才是最好的

一是我们看中它容易学习,开发效率高,运营也不错。两个人在工作之余,相当于工作的 20% 的时间,团队一个月就弄了一个版本出来,我们觉得还不错。

二是部署很简单,部署的时候就是二进制,很小没有依赖,服务器只要不是太老的系统部署十分简单轻便。

最后一个就是适合自己的才是最好的,Go 语言对我们公司来讲实现的成本是最低的,是最适合我们的,在我们的眼里是最好的

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20171220B03UO600?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券