【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搭建和管理企业级网站应用
目录
相关文章
|
2月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
348 37
|
3月前
|
Kubernetes 监控 API
在K8S中,什么是 Minikube、Kubectl、Kubelet?
在K8S中,什么是 Minikube、Kubectl、Kubelet?
|
3月前
|
设计模式 存储 缓存
Guava 源码中7种设计模式的实现分析
V 哥在学习 Guava 源码中总结的7个设计模式的实现分析,欢迎关注威哥爱编程,做自己的技术,让别人去卷吧。
|
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
46 0
|
3月前
|
Kubernetes 监控 Shell
掌握Kubernetes故障排除技巧:kubectl命令的基本指南
以上是使用 `kubectl` 进行故障排除的一些基本指南。熟悉这些命令能够帮助您快速定位和解决在Kubernetes集群中遇到的问题。在实际使用中,您可能还需要结合其他工具和资源,如官方文档、社区论坛以及第三方监控和日志服务来进行更深入的故障诊断和排除。
95 0
|
4月前
|
Kubernetes 应用服务中间件 nginx
深入了解 `kubectl`:Kubernetes 命令行工具
深入了解 `kubectl`:Kubernetes 命令行工具
169 1
|
6月前
|
设计模式 安全 Java
【初学者慎入】Spring源码中的16种设计模式实现
以上是威哥给大家整理了16种常见的设计模式在 Spring 源码中的运用,学习 Spring 源码成为了 Java 程序员的标配,你还知道Spring 中哪些源码中运用了设计模式,欢迎留言与威哥交流。
287 3
|
6月前
|
设计模式 算法 Java
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式

推荐镜像

更多