天天看點

結合簡單的控制台程式和K8S的cronjob完成定時任務

前言

老黃前段時間遇到了一個資料清洗的需求,其實就是每天淩晨把昨天的資料清洗一遍,歸歸類。

這是一個比較典型的定時任務的處理場景。

定時任務可以說就一把利器,幾乎每個公司都離不開,它的應用場景也不在少數,比如:

  1. 生成前一天的統計資料
  2. 每隔幾天清理一次日志
  3. 定期處理失效的單據
  4. ...

對于定時任務,常見的解決方案有下面幾種

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

對于1和2,無疑是要投入學習成本的,要習慣它們的用法,不好的地方就是不能讓開發人員集中精力去處理業務上面的内容。

對于3和4,這兩個算是分布式任務排程的平台,很好的與業務解耦了,可以通過HTTP的接口來觸發任務的執行。

3和4想在生産環境高可用,離不開叢集部署,在資源緊張的時候其實想部署這麼一套東西其實還是挺不容易的。

對于上面的幾種方案,老黃都沒有采用,卻而代之的是k8s的cronjob。

為什麼選擇cronjob

上面提到的幾種方案,也已經表達了不選用的原因了,無非就是成本和複雜度,下面來講講選擇k8s的cronjob的原因吧。

首先k8s的cronjob本身就可以當作是一個任務排程的平台了,排程的時候會建立一個POD來執行我們的任務。

其次的話,沒有複雜的依賴關系,隻要編寫一個簡單的控制台程式就好了。

還有一個是成本問題,老黃公司用的k8s是serverless的,沒有實實在在的伺服器資源,傳遞的隻是鏡像,執行這些定時任務,都是按時間計費的。

1C2G的配置隻要0.00006126塊錢一秒,假設你的任務執行要3分鐘,那這一次任務隻要1毛錢就可以了。

結合簡單的控制台程式和K8S的cronjob完成定時任務

選擇什麼配置,最後要看的還是你業務的需要。

說了這麼多,來個僞例子吧。

簡單例子

要先準備一下我們的任務内容,其實就是寫個簡單的控制台程式。

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完成定時任務

點詳情可以看到具體的執行情況。

結合簡單的控制台程式和K8S的cronjob完成定時任務

寫在最後

定時任務這個問題的答案有很多種解法,可以選擇适合公司的最優解。

因為每種解法都有它好或者不好的地方,k8s的cronjob也是有它不足的地方的,最為明顯的就是cron表達式第1位是分鐘而不是秒,也就是說最小粒度隻到分鐘,如果你的應用需要到秒的,可能就沒辦法支援到了。

結合簡單的控制台程式和K8S的cronjob完成定時任務

如果您認為這篇文章還不錯或者有所收獲,可以點選右下角的【推薦】按鈕,因為你的支援是我繼續寫作,分享的最大動力!

作者:Catcher Wong ( 黃文清 )

來源:http://catcher1994.cnblogs.com/

聲明:

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。如果您發現部落格中出現了錯誤,或者有更好的建議、想法,請及時與我聯系!!如果想找我私下交流,可以私信或者加我微信。