zoukankan      html  css  js  c++  java
  • 结合简单的控制台程序和K8S的cronjob完成定时任务

    前言

    老黄前段时间遇到了一个数据清洗的需求,其实就是每天凌晨把昨天的数据清洗一遍,归归类。

    这是一个比较典型的定时任务的处理场景。

    定时任务可以说就一把利器,几乎每个公司都离不开,它的应用场景也不在少数,比如:

    1. 生成前一天的统计数据
    2. 每隔几天清理一次日志
    3. 定期处理失效的单据
    4. ...

    对于定时任务,常见的解决方案有下面几种

    1. quartz.net
    2. hangfire
    3. xxl-job
    4. saturn
    5. ...

    对于1和2,无疑是要投入学习成本的,要习惯它们的用法,不好的地方就是不能让开发人员集中精力去处理业务上面的内容。

    对于3和4,这两个算是分布式任务调度的平台,很好的与业务解耦了,可以通过HTTP的接口来触发任务的执行。

    3和4想在生产环境高可用,离不开集群部署,在资源紧张的时候其实想部署这么一套东西其实还是挺不容易的。

    对于上面的几种方案,老黄都没有采用,却而代之的是k8s的cronjob。

    为什么选择cronjob

    上面提到的几种方案,也已经表达了不选用的原因了,无非就是成本和复杂度,下面来讲讲选择k8s的cronjob的原因吧。

    首先k8s的cronjob本身就可以当作是一个任务调度的平台了,调度的时候会创建一个POD来执行我们的任务。

    其次的话,没有复杂的依赖关系,只要编写一个简单的控制台程序就好了。

    还有一个是成本问题,老黄公司用的k8s是serverless的,没有实实在在的服务器资源,交付的只是镜像,执行这些定时任务,都是按时间计费的。

    1C2G的配置只要0.00006126块钱一秒,假设你的任务执行要3分钟,那这一次任务只要1毛钱就可以了。

    选择什么配置,最后要看的还是你业务的需要。

    说了这么多,来个伪例子吧。

    简单例子

    要先准备一下我们的任务内容,其实就是写个简单的控制台程序。

    using System;
    
    internal class Program
    {
        private static void Main(string[] args)
        {
            // 写这个定时任务要处理的内容
            
            Console.WriteLine($"Hello World!  {a}");
        }
    }
    

    这里有一个要注意的是,不要出现 Console.ReadLine, Console.ReadKey之类的东西,不然是run不起来的。

    Dockerfile就不写了,只要能把这个控制台程序打包成一个镜像,可以run起来就可以了。

    后面就是写cronjob的配置了。

    apiVersion: batch/v1beta1
    kind: CronJob
    metadata:
      labels:
        etl: diagnosis
      name: xyzxyz
      namespace: prod
    spec:
      # 禁止并发运行
      concurrencyPolicy: Forbid
      failedJobsHistoryLimit: 1
      jobTemplate:
        metadata: {}
        spec:
          # 指定存活时长
          activeDeadlineSeconds: 1200
          # 指定失败时可以重试2次
          backoffLimit: 2
          completions: 1
          parallelism: 1
          template:
            spec:
              containers:
                - env:
                    - name: DOTNET_RUNNING_IN_CONTAINER
                      value: 'true'
                    - name: TZ
                      value: Asia/Shanghai
                  image: >-
                    xxxxx:5000/xxxxx:version
                  imagePullPolicy: IfNotPresent
                  name: xyzxyz
                  ports:
                    - containerPort: 80
                      protocol: TCP
                  resources:
                    # 这里只用了0.25C 0.5G
                    requests:
                      cpu: 250m
                      memory: 512Mi
                  terminationMessagePath: /dev/termination-log
                  terminationMessagePolicy: File
              dnsPolicy: ClusterFirst
              restartPolicy: Never
              schedulerName: default-scheduler
      # cron表达式,
      schedule: 22 4 1/1 * ?
      # 成功job历史显示个数
      successfulJobsHistoryLimit: 1
    

    里面的配置其实还是挺多的,对老黄的场景来说,上面的配置足够了,对更多的配置,可以参考k8s的官网。

    执行kubectl apply -f xxx.yml 就可以创建定时任务了,后面就会自动调度执行对应的任务了。

    这里就不执行了,直接拿线上正在跑的三个定时任务给大家参考一下。

    点详情可以看到具体的执行情况。

    写在最后

    定时任务这个问题的答案有很多种解法,可以选择适合公司的最优解。

    因为每种解法都有它好或者不好的地方,k8s的cronjob也是有它不足的地方的,最为明显的就是cron表达式第1位是分钟而不是秒,也就是说最小粒度只到分钟,如果你的应用需要到秒的,可能就没办法支持到了。

  • 相关阅读:
    PHP生成PDF并转换成图片爬过的坑
    PHAR系列之导言
    Linux学习之路(三)Shell脚本初探
    Linux学习之路(二)
    php 隐藏手机号中间几位
    tp 递归菜单列表【树状】
    php导出excel封装类
    php 导出Excel表格
    php字符串之翻转单词顺序列
    laravel实现跳转其他控制器
  • 原文地址:https://www.cnblogs.com/catcher1994/p/14022674.html
Copyright © 2011-2022 走看看