JDKHOME JDKHOME
  • Web

    • 权限框架Twiggy
    • 脚手架BLZO
  • 杂货
技术思考
  • Kubernetes
  • 文档
  • jdkhome
  • 友链
  • 版权声明
  • 分类
  • 标签
  • 归档
  • Web

    • 权限框架Twiggy
    • 脚手架BLZO
  • 杂货
技术思考
  • Kubernetes
  • 文档
  • jdkhome
  • 友链
  • 版权声明
  • 分类
  • 标签
  • 归档
  • 分布式定时任务解决方案

    • 背景
      • 一些思路
        • 1.抽离定时任务单独部署
        • 2.抽离定时任务调度服务
        • 3.定时任务执行Flag
      • 一些轮子
        • Quartz 、 elastic-job
        • xxl-job
      • 我的方案
        • 参考文档
        • 思考
        linkji
        2019-10-22

        分布式定时任务解决方案

        # 分布式定时任务解决方案

        # 背景

        定时任务在各种业务下都有广泛的使用, 一般来说定时任务和业务服务关联紧密, 开发的时候把他们写在一起很方便。
        但是在分布式多节点的部署模式下, 执行同一个定时任务的应用可能会被部署多个实例。每个实例在同一个时间点都会执行相同的定时任务。这会造成资源的浪费,一些特殊业务重复执行甚至可能造成严重的错误(如结算业务)。
        本文基于微服务的架构, 进一步的探讨, 分布式定时任务的解决方案。

        # 一些思路

        # 1.抽离定时任务单独部署

        最简单的方法, 做一个开关, 控制启动的应用是否要执行定时任务。然后将要执行定时任务的应用"特殊照顾"单独部署一份。既不影响业务系统, 也不用再担心重复执行。

        这种方案要注意确保执行任务的实例不能挂, 或者挂了立即告警。

        # 2.抽离定时任务调度服务

        每个实例都有能力执行定时任务, 但是定时任务由外部的调度服务统一触发。

        可以使用http请求作为定时任务的触发方法, 配合网关, 使资源的每一个请求只会到达某一个实例, 这样定时任务也能够实现"负载均衡"。

        # 3.定时任务执行Flag

        就像分布式锁的处理方法一样, 执行前先获取锁, 无法获取锁就说明任务正在由其他实例执行。此时定时任务就会有排他性, 即可保证唯一执行。

        关联项目 blzo-ex-task 分布式定时任务 : 基于这个理论实现的分布式定时任务框架。

        # 一些轮子

        (下面几个服务, 我都没有深度使用过, 如有写错, 请指正哈)

        主要还是基于 2和3 现成就有许多可选的方案:

        # Quartz 、 elastic-job

        Quartz基于方案3, 但是更加完善, 处理保证唯一执行外, 还会更具执行结果(成功/失败)来控制是否重试。

        Elastic-job 是由当当网基于quartz 二次开发之后的分布式调度解决方案, 在quartz的基础上进一步的增强了管理、分布式等功能。

        # xxl-job

        基于方案2, 实现了一个可视化的调度中心。

        # 我的方案

        个人认为, 使用调度中心来实现分布式定时任务比Flag的方案更加成熟。 但是同时, 使用xxl-job又觉得有些太重了。

        结合项目的实际运行环境(k8s), 我整理出下面的实现方案:

        实现一个定时任务触发器(比较简单就不贴代码了):

        ./task -url 请求地址 -token 钉钉机器人token
        
        1
        • 向指定地址发POST请求
        • 根据项目的返回数据判断定时任务十分执行成功
        • 顺利执行程序返回系统调用code 0 失败返回 1

        然后打到docker做成镜像

        接下来将想要控制触发的定时任务,以CronJob的方式部署至k8s集群中:

        xxx-task-cronjob.yaml

        apiVersion: batch/v1beta1
        kind: CronJob
        metadata:
          name: xxx-task-cronjob
        spec:
          schedule: "0 * * * *" # corn表达式设置执行
          successfulJobsHistoryLimit: 0 # 不保留成功历史
          failedJobsHistoryLimit: 0 # 不保留失败历史
          jobTemplate:
            spec:
              template:
                spec:
                  containers:
                  - name: xxx-task-cronjob
                    image: task:latest
                    command: 
                    - "./task"
                    args:
                    - "-url"
                    - "http://xxxx-service:xxxx/api/xxxx" # 指定定时任务触发地址
                    - "-token"
                    - "xxxxxxxxxxxxxxxxxxxxx" # 出现异常钉钉告警, 这里填钉钉群token
                  restartPolicy: OnFailure # 异常退出则重试
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23

        如此一来, 一个高可靠性的轻量的定时任务调度器就完成了!

        # 参考文档

        • 分布式定时任务调度框架 偶像本人
        • 【解决方案】分布式定时任务解决方案 CoffeJoy
        • CronJob介绍 kubernetes.io
        上次更新: 2020/06/11, 18:06:00
        最近更新
        01
        搭建redis
        11-21
        02
        istio安装
        10-25
        03
        搭建K8S高可用集群
        09-13
        更多文章>
        鄂ICP备15015406号 | Copyright © 2015-2020 jdkhome
        • 跟随系统
        • 浅色模式
        • 深色模式
        • 阅读模式