写点什么

Kubernetes 中定时任务的实现

  • 2020-01-10
  • 本文字数:2073 字

    阅读完需:约 7 分钟

Kubernetes 中定时任务的实现

Kubernetes 中定时任务的实现

K8s 中有许多优秀的包都可以在平时的开发中借鉴与使用,比如,任务的定时轮询、高可用的实现、日志处理、缓存使用等都是独立的包,可以直接引用。


本文将介绍 K8s 中定时任务的实现,K8s 中定时任务都是通过 wait 包实现的。wait 包在 K8s 的多个组件中都有用到,以下是 wait 包在 kubelet 中的几处使用:


func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan struct{}) (err error) {



// kubelet 每 5 分钟一次从 apiserver 获取证书


closeAllConns, err := kubeletcertificate.UpdateTransport(wait.NeverStop, clientConfig, clientCertificateManager, 5*time.Minute)


if err != nil {


return err


}


closeAllConns, err := kubeletcertificate.UpdateTransport(wait.NeverStop, clientConfig, clientCertificateManager, 5*time.Minute)


if err != nil {


return err


}



}



func startKubelet(k kubelet.Bootstrap, podCfg *config.PodConfig, kubeCfg *kubeletconfiginternal.KubeletConfiguration, kubeDeps *kubelet.Dependencies, enableServer bool) {


// 持续监听 pod 的变化


go wait.Until(func() {


k.Run(podCfg.Updates())


}, 0, wait.NeverStop)



}


golang 中可以通过 time.Ticker 实现定时任务的执行,但在 K8s 中用了更原生的方式,使用 time.Timer 实现的。time.Ticker 和 time.Timer 的使用区别如下:


  • ticker 只要定义完成,从此刻开始计时,不需要任何其他的操作,每隔固定时间都会自动触发。

  • timer 定时器是到了固定时间后会执行一次,仅执行一次

  • 如果 timer 定时器要每隔间隔的时间执行,实现 ticker 的效果,使用 func (t *Timer) Reset(d Duration) bool


一个示例:


package main


import (


“fmt”


“sync”


“time”


)func main() {


var wg sync.WaitGroup timer1 := time.NewTimer(2 * time.Second)


ticker1 := time.NewTicker(2 * time.Second) wg.Add(1)


go func(t *time.Ticker) {


defer wg.Done()


for {


<-t.C


fmt.Println(“exec ticker”, time.Now().Format(“2006-01-02 15:04:05”))


}


}(ticker1) wg.Add(1)


go func(t *time.Timer) {


defer wg.Done()


for {


<-t.C


fmt.Println(“exec timer”, time.Now().Format(“2006-01-02 15:04:05”))


t.Reset(2 * time.Second)


}


}(timer1) wg.Wait()


}01


wait 包中的核心代码


核心代码


k8s.io/apimachinery/pkg/util/wait/wait.go:


func JitterUntil(f func(), period time.Duration, jitterFactor float64, sliding bool, stopCh <-chan struct{}) {


var t *time.Timer


var sawTimeout bool


for {


select {


case <-stopCh:


return


default:


} jitteredPeriod := period


if jitterFactor > 0.0 {


jitteredPeriod = Jitter(period, jitterFactor)


} if !sliding {


t = resetOrReuseTimer(t, jitteredPeriod, sawTimeout)


} func() {


defer runtime.HandleCrash()


f()


}() if sliding {


t = resetOrReuseTimer(t, jitteredPeriod, sawTimeout)


} select {


case <-stopCh:


return


case <-t.C:


sawTimeout = true


}


}


}…


func resetOrReuseTimer(t *time.Timer, d time.Duration, sawTimeout bool) *time.Timer {


if t == nil {


return time.NewTimer(d)


}


if !t.Stop() && !sawTimeout {


<-t.C


}


t.Reset(d)


return t


}几个关键点的说明:


  1. 如果 sliding 为 true,则在 f() 运行之后计算周期。如果为 false,那么 period 包含 f() 的执行时间。

  2. 在 golang 中 select 没有优先级选择,为了避免额外执行 f(),在每次循环开始后会先判断 stopCh chan。


K8s 中 wait 包其实是对 time.Timer 做了一层封装实现。


02


wait 包常用的方法


定期执行一个函数,永不停止,可以使用 Forever 方法:


func Forever(f func(), period time.Duration)


在需要的时候停止循环,那么可以使用下面的方法,增加一个用于停止的 chan 即可,方法定义如下:


func Until(f func(), period time.Duration, stopCh <-chan struct{})


上面的第三个参数 stopCh 就是用于退出无限循环的标志,停止的时候我们 close 掉这个 chan 就可以了。


有时候,我们还会需要在运行前去检查先决条件,在条件满足的时候才去运行某一任务,这时候可以使用 Poll 方法:


func Poll(interval, timeout time.Duration, condition ConditionFunc)


这个函数会以 interval 为间隔,不断去检查 condition 条件是否为真,如果为真则可以继续后续处理;如果指定了 timeout 参数,则该函数也可以只常识指定的时间。


PollUntil 方法和上面的类似,但是没有 timeout 参数,多了一个 stopCh 参数,如下所示:


PollUntil(interval time.Duration, condition ConditionFunc, stopCh <-chan struct{}) error


此外还有 PollImmediate 、 PollInfinite 和 PollImmediateInfinite 方法。


03


总结


本文主要讲了 K8s 中定时任务的实现与对应包(wait)中方法的使用。


通过阅读 K8s 的源代码,可以发现 K8s 中许多功能的实现也都是我们需要在平时工作中用的,其大部分包的性能都是经过大规模考验的,通过使用其相关的工具包不仅能学到大量的编程技巧也能避免自己造轮子。


原文:https://dwz.cn/5zxd9ZqU


2020-01-10 13:531431

评论

发布
暂无评论
发现更多内容

为什么外贸行业选择使用云手机?

Ogcloud

云手机 海外云手机 云手机海外版 国外云手机

今日分享丨按场景定制界面

inBuilder低代码平台

界面 开发分享

一文看懂可观测:盯得住系统,扛得住稳定

阿里巴巴云原生

阿里云 云原生 可观测

华为大咖说 | 企业应用AI大模型的“道、法、术”—— 法:场景篇

华为云PaaS服务小智

人工智能 华为云 企业数字化

探索区块链交易所的开发之路

dappweb

交易所开发 区块链开发

一站式链路追踪:阿里云的端到端解决方案

阿里巴巴云原生

阿里云 云原生 可观测

软件测试学习笔记丨Selenium 配置浏览器启动状态Options

测试人

软件测试

低代码开发与前端架构

不在线第一只蜗牛

架构 前端 低代码

活动回顾 | 「观测云」为何成为中国峰会可观测性领域的唯一代表?

观测云

AWS

Apache IoTDB 分布式架构三部曲(二)分片与负载均衡

Apache IoTDB

Python零基础“圣经”!300W小白从入门到精通首选!

我再BUG界嘎嘎乱杀

Python 入门 零基础

海外云手机运营TikTok:高效、稳定且节省流量

Ogcloud

云手机 海外云手机 tiktok云手机 云手机海外版 电商云手机

如何使用前端表格控件实现多数据源整合?

快乐非自愿限量之名

前端 表格控件

发现了一个全新的后台管理框架,前后端都有

大师兄

Vue 开源框架 nest

ETLCloud中如何使用Kettle组件

RestCloud

kettle ETL 数据集成 ETLCloud

Pandas数据读取三连“坑”

我再BUG界嘎嘎乱杀

Python 后端 开发语言

Django 实现用户需求及反馈系统并支持图片上传

我再BUG界嘎嘎乱杀

Python django 爬虫 后端 开发语言

低代码:全生命周期管理的技术革新与应用实践

EquatorCoco

低代码 全生命周期

从人工向智能化转变,企业级指标管理平台建设实战

袋鼠云数栈

指标管理 指标建设 指标设计 指标设计指标体系 指标搭建

低代码与大模型时代:技术的进化与人工智能的普及

快乐非自愿限量之名

人工智能 低代码 大模型

性能突破|海量客户端场景 Quota 和 QoS 的优化之路

焱融科技

打造高效微服务最佳实践

俞凡

架构 微服务

Scroll 生态明星项目Pencils Protocol,发展潜力巨大

大瞿科技

Scroll 生态明星项目Pencils Protocol,发展潜力巨大

加密眼界

API测试工具领域,Postman的10个最佳替换

幂简集成

Postman API API测试 API测试工具

什么是数据资产管理?数据资产管理包括了哪些内容?

优秀

数据资产管理

Kubernetes 中定时任务的实现_语言 & 开发_华为云原生团队_InfoQ精选文章