基于etcd的分布式定时任务框架

来源:互联网 发布:thinkphp 子域名部署 编辑:程序博客网 时间:2024/06/01 03:58

  在开发过程中,往往需要系统执行一些定时的任务,例如我们需要将数据进行迁移,又或者需要做一些数据的离线统计工作,这些都需要定时任务来进行处理。传统的方法就是quartz来写个定时任务,然后该机器就会在特定时间执行我们要执行的代码,但是假如这台机器出现故障,那么这个定时任务就不会执行。
  在集群环境中,我们希望即使在某台机器出现故障,那么其他机器就可以将任务接管过来,继续执行任务。
项目github:https://github.com/Mrfogg/gojob

使用方式

如下代码,我的机器已经部署了etcd,端口是2379

package gojobimport (    "testing"    "fmt"    "github.com/coreos/etcd/clientv3")var client *clientv3.Client//初始化etcd client对象func init() {    var err error    client, err = clientv3.New(clientv3.Config{Endpoints: []string{        "localhost:2379",    }})    if err != nil {        panic("new client of etcd fail")    }}//实现job接口type testJob struct {}func (t *testJob) GetName() string {    return "testjob"}func (t *testJob) Run() {    fmt.Println("test job runing")}func (t *testJob) Stop() {    fmt.Println("test job stop")}func TestGojob(t *testing.T) {    gj, err := NewGoJobByEtcd(client, "test", "node1")    if err != nil {        t.Error("new gojob fail")    }    gj.AddJob("*/5 * * * * ?", new(testJob)) //cron表达式控制执行时间    gj.StartAll()    c := make(chan int) //这里的作用更是让主协程序挂起等待    <-c}

源码解析

  代码主要分为如下几个部分:

  1. 时间表达式解析。这里借鉴了https://github.com/robfig/cron,但是这个项目没有对任务的停止或删除操作,不太满足我的需求,所以做了一些修改。代码为cron文件夹。
  2. 节点心跳。NewGojobByEtcd 除了etcd的客户端实例,还需要一个key以及node名。每一个gojob会定时将prefix+node作为Key写入etcd,并且这个Key有一个过期时间。写入的间隔时间小于过期时间。这样就可以理解为etcd中的这个定时写入的key若存在,那么那个定时写入这个key的机器或进程是存活的。f

    func (p *HTTPPool) heartBeat() {    tick := time.Tick(time.Second * 15)    for {        select {        case <-tick:            p.etcdDb.PutTTL(p.Self, "", time.Second*25) //p.self = prefix+nodename,        }    }}

    3.一致性哈希。gojob会监听自己对应的prefix的key,并且以这些key做一致性哈希。当一个新添加一个定时任务时(任务实现了GetName()方法),通过任务名的哈希值来决定这个任务是否属于自己的任务。若是则执行,若不是则不执行。当有节点挂掉的时候,gojob会重新构建一致性哈希,那么就会将挂掉的机器的任务接管过来。从而实现容错的机制。

如果对您有所帮助,在github上点个小星星吧^^

阅读全文
0 0
原创粉丝点击