【K8s源码品读】003:Phase 1 - kubectl - 设计模式中Visitor的实现

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 理解kubectl的核心实现之一:Visitor Design Pattern 访问者模式

聚焦目标

理解kubectl的核心实现之一:Visitor Design Pattern 访问者模式

目录

  1. 什么是访问者模式

  2. kubectl中的Visitor

  3. Visitor的链式处理

    1. 多个对象聚合为一个对象
      1. VisitorList
      2. EagerVisitorList
    2. 多个方法聚合为一个方法
      1. DecoratedVisitor
      2. ContinueOnErrorVisitor
    3. 将对象抽象为多个底层对象,逐个调用方法
      1. FlattenListVisitor
      2. FilteredVisitor
  4. Visitor的各类实现

    1. StreamVisitor
    2. FileVisitor
    3. URLVisitor
    4. KustomizeVisitor

visitor design pattern

在设计模式中,访问者模式的定义为:

允许一个或者多个操作应用到对象上,解耦操作和对象本身

那么,对一个程序来说,具体的表现就是:

  1. 表面:某个对象执行了一个方法
  2. 内部:对象内部调用了多个方法,最后统一返回结果

举个例子,

  1. 表面:调用一个查询订单的接口
  2. 内部:先从缓存中查询,没查到再去热点数据库查询,还没查到则去归档数据库里查询

Visitor

我们来看看kubeadm中的访问者模式的定义:

// Visitor 即为访问者这个对象
type Visitor interface {
   
    Visit(VisitorFunc) error
}
// VisitorFunc对应这个对象的方法,也就是定义中的“操作”
type VisitorFunc func(*Info, error) error

基本的数据结构很简单,但从当前的数据结构来看,有两个问题:

  1. 单个操作 可以直接调用Visit方法,那多个操作如何实现呢?
  2. 在应用多个操作时,如果出现了error,该退出还是继续应用下一个操作呢?

Chained

VisitorList

封装多个Visitor为一个,出现错误就立刻中止并返回

// VisitorList定义为[]Visitor,又实现了Visit方法,也就是将多个[]Visitor封装为一个Visitor
type VisitorList []Visitor

// 发生error就立刻返回,不继续遍历
func (l VisitorList) Visit(fn VisitorFunc) error {
   
    for i := range l {
   
        if err := l[i].Visit(fn); err != nil {
   
            return err
        }
    }
    return nil
}

EagerVisitorList

封装多个Visitor为一个,出现错误暂存下来,全部遍历完再聚合所有的错误并返回

// EagerVisitorList 也是将多个[]Visitor封装为一个Visitor
type EagerVisitorList []Visitor

// 返回的错误暂存到[]error中,统一聚合
func (l EagerVisitorList) Visit(fn VisitorFunc) error {
   
    errs := []error(nil)
    for i := range l {
   
        if err := l[i].Visit(func(info *Info, err error) error {
   
            if err != nil {
   
                errs = append(errs, err)
                return nil
            }
            if err := fn(info, nil); err != nil {
   
                errs = append(errs, err)
            }
            return nil
        }); err != nil {
   
            errs = append(errs, err)
        }
    }
    return utilerrors.NewAggregate(errs)
}

DecoratedVisitor

这里借鉴了装饰器的设计模式,将一个Visitor调用多个VisitorFunc方法,封装为调用一个VisitorFunc

// 装饰器Visitor
type DecoratedVisitor struct {
   
    visitor    Visitor
    decorators []VisitorFunc
}

// visitor遍历调用decorators中所有函数,有失败立即返回
func (v DecoratedVisitor) Visit(fn VisitorFunc) error {
   
    return v.visitor.Visit(func(info *Info, err error) error {
   
        if err != nil {
   
            return err
        }
        for i := range v.decorators {
   
            if err := v.decorators[i](info, nil); err != nil {
   
                return err
            }
        }
        return fn(info, nil)
    })
}

ContinueOnErrorVisitor

// 报错依旧继续
type ContinueOnErrorVisitor struct {
   
    Visitor
}

// 报错不立即返回,聚合所有错误后返回
func (v ContinueOnErrorVisitor) Visit(fn VisitorFunc) error {
   
    errs := []error{
   }
    err := v.Visitor.Visit(func(info *Info, err error) error {
   
        if err != nil {
   
            errs = append(errs, err)
            return nil
        }
        if err := fn(info, nil); err != nil {
   
            errs = append(errs, err)
        }
        return nil
    })
    if err != nil {
   
        errs = append(errs, err)
    }
    if len(errs) == 1 {
   
        return errs[0]
    }
    return utilerrors.NewAggregate(errs)
}

FlattenListVisitor

将runtime.ObjectTyper解析成多个runtime.Object,再转换为多个Info,逐个调用VisitorFunc

type FlattenListVisitor struct {
   
    visitor Visitor
    typer   runtime.ObjectTyper
    mapper  *mapper
}

FilteredVisitor

对Info资源的检验

// 过滤的Info
type FilteredVisitor struct {
   
    visitor Visitor
    filters []FilterFunc
}

func (v FilteredVisitor) Visit(fn VisitorFunc) error {
   
    return v.visitor.Visit(func(info *Info, err error) error {
   
        if err != nil {
   
            return err
        }
        for _, filter := range v.filters {
   
      // 检验Info是否满足条件,出错则退出
            ok, err := filter(info, nil)
            if err != nil {
   
                return err
            }
            if !ok {
   
                return nil
            }
        }
        return fn(info, nil)
    })
}

Implements

StreamVisitor

最基础的Visitor

type StreamVisitor struct {
   
  // 读取信息的来源,实现了Read这个接口,这个"流式"的概念,包括了常见的HTTP、文件、标准输入等各类输入
    io.Reader
    *mapper

    Source string
    Schema ContentValidator
}

FileVisitor

文件的访问,包括标准输入,底层调用StreamVisitor来访问

type FileVisitor struct {
   
  // 表示文件路径或者STDIN
    Path string
    *StreamVisitor
}

URLVisitor

HTTP用GET方法获取数据,底层也是复用StreamVisitor

type URLVisitor struct {
   
    URL *url.URL
    *StreamVisitor
  // 提供错误重试次数
    HttpAttemptCount int
}

KustomizeVisitor

自定义的Visitor,针对自定义的文件系统

type KustomizeVisitor struct {
   
    Path string
    *StreamVisitor
}
相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
7天前
|
Kubernetes 应用服务中间件 nginx
【赵渝强老师】Kubernetes命令行管理工具:kubectl
kubectl 是 Kubernetes 的命令行工具,用于管理和操作 Kubernetes 集群。本文通过视频讲解和具体示例,介绍了 kubectl 的常用命令,包括显示 Pod 信息、创建 Deployment 和 Service、更新和回滚 Deployment、以及删除资源等操作。
|
2月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
405 37
|
3月前
|
Kubernetes 监控 API
在K8S中,什么是 Minikube、Kubectl、Kubelet?
在K8S中,什么是 Minikube、Kubectl、Kubelet?
|
3月前
|
Kubernetes API 容器
在k8S中,使用kubectl logs无法查看日志是什么原因,如何让其能够查看?
在k8S中,使用kubectl logs无法查看日志是什么原因,如何让其能够查看?
|
3月前
|
Kubernetes 监控 API
在K8S中,Minikube、Kubectl、Kubelet是什么?
在K8S中,Minikube、Kubectl、Kubelet是什么?
|
3月前
|
Kubernetes 容器
Kubernetes(K8S) 安装 Metrics-Server kubectl top (metrics-server) node NotFound
Kubernetes(K8S) 安装 Metrics-Server kubectl top (metrics-server) node NotFound
49 0
|
22天前
|
JSON Kubernetes 容灾
ACK One应用分发上线:高效管理多集群应用
ACK One应用分发上线,主要介绍了新能力的使用场景
|
23天前
|
Kubernetes 持续交付 开发工具
ACK One GitOps:ApplicationSet UI简化多集群GitOps应用管理
ACK One GitOps新发布了多集群应用控制台,支持管理Argo CD ApplicationSet,提升大规模应用和集群的多集群GitOps应用分发管理体验。
|
1月前
|
Kubernetes Cloud Native 云计算
云原生之旅:Kubernetes 集群的搭建与实践
【8月更文挑战第67天】在云原生技术日益成为IT行业焦点的今天,掌握Kubernetes已成为每个软件工程师必备的技能。本文将通过浅显易懂的语言和实际代码示例,引导你从零开始搭建一个Kubernetes集群,并探索其核心概念。无论你是初学者还是希望巩固知识的开发者,这篇文章都将为你打开一扇通往云原生世界的大门。
120 17
|
1月前
|
Kubernetes 应用服务中间件 nginx
搭建Kubernetes v1.31.1服务器集群,采用Calico网络技术
在阿里云服务器上部署k8s集群,一、3台k8s服务器,1个Master节点,2个工作节点,采用Calico网络技术。二、部署nginx服务到k8s集群,并验证nginx服务运行状态。
453 1